Nov 23, 2019
Nov 14, 2020
Chainsaw was an interesting box that I thoroughly enjoyed. Upon first investigation an anonymous ftp connection allowed access to some intersting files. Further investigation led to an understanding that those files were smart contract related and ultimately required to connect and exploit a foothold. From the initial foothold we extracted sensitive private keys from the local InterPlanetary File System and cracked password protected ssh private keys for user pivot. From user we exploited a loosely defined SUID file and PATH hijacking for root shell then finally leveraged root.txt's slack space to get the final flag.
As the first time working with smart contracts it was an interesting initial vector filled with research into understanding how they worked in general as well as how we can use this to our advantage. Overall, I really enjoyed this box from that angle. The only part I did not enjoy was the final slack space of the flag. Without any direct need to include this step it felt forced and contrived. With that said however I had not directly interacted with hidden data in this manner before therefore I am thankful that I had the opportunity to expand that knowledge.
Let's kick it off with an nmap scan:
That's a lot text but breaking it down it's essentially anonymous access ftp, ssh and finally an unrecognized service running on 9810. Since we know the obvious access through ftp let's take a quick poke at what we can find.
Hum...no idea what these files are. Let's pull back to our host and explore them a bit more.
While I can understand that the .sol file is essentially setting up a "WeaponizedPing" object with get/set functionality still wasn't entirely sure how it worked. A quick search online and learned that these are Ethereum smart contract files. This python web3.py article was invaluable in not only understanding the basics but getting a quick-and-dirty script up to connect with the smart contract. Based on the article we can assume that port 9810 from our nmap scan above is how we will connect and we should set up our provider to point here. Since we had the address from address.txt and the abi and bytecode from WeaponizedPing.json and what functions are available through WeaponizedPing.sol we should be able to follow along and interact with it. My script ended up being the following:
We are able to then test, connect and leverage the functions of the smart contract. Awesome!
I had a hunch here that whatever address was present in the store variable would actually be pinged. Decided to test this out by setting up wireshark and attempting to modify the store to point to my IP. Sure enough that also worked.
So we know that we know we can control the variable and that the functionality gets called under the hood, how can we leverage this to our advantage. Let's see if we can chain together a nc call back to a local listener. This is assuming several things including that nc is installed on the host, however figured this would be the path of least resistance so let's give it a shot.
Beautiful! Initial foothold established. Unfortunately administrator did not end up being the true "user" in this case so we need to pivot further for our first flag.
Checking administrator's homedir we see quite a few things.
Right off the bat we see some users within the csv file.
Digging slightly deeper we find a folder which includes an interesting python script.
I decided to get it a shot and see what gets generated.
As a result ended up generating an SSH keypair. Transferring them over to my host I took a close look.
Ok, so the private key is password protected by the password we passed in the gen.py script. Additionally it looks like it's DES-EDE3-CBC encryted with a defined salt, in this case 13F6FF16239B8B00. I went through a few iterations of gen.py to see if there were any flaws with how it generated the keypairs. While the settings were the same the salt seems to be random on each pair. Still testing a few things I found sshng2john to generate a JTR hash to crack. Sure enough I was able to crack my test keypair.
While we had access to the public keys in the pub/ folder on the host, the private keys were not found. There was however a comment in the script of "TODO: Distribute keys via ProtonMail". Let's see if there are any crumbs left around in the host.
From the home directory I noticed a .ipfs folder. Taking a peek within the folder there are many blocks. Instead of checking block by block let's just dump everything and take a look at what we can see.
Now we're talking! Ok, looks like they're base64 encoded, so let's get the ouput.
Perfect, with bobby's private key we should be able to reproduct the sshng2john to generate the password hash and crack it using JTR.
And with that we should be able to use the private key to ssh in as bobby.
Now that we have user access we need to start enumerating for a vector to root.
Digging slightly deeper into the projects folder we happen upon a nice SUID file. Very interesting!
Let's pull that file over to our local instance. My thoughts at this point were we are going to need to do a little bit of RE to make the jump. I booted up ghidra to take a look at the decompile... and was thoroughly surprised at what I found.
Facepalm moment here is where I spent an hour or two trying to figure out how I could overwrite the ChainsawClub call. I even went so far as to modify the hex of the binary and upload it back to the host. Clearly that did not get me very far. Spent a bit of time taking a step back to tackle it at a different angle.This article was among those I perused and that's when it hit me. The ChainsawClub portion was full defined, but sudo itself was loosely defined! Since the binary is calling setuid(0) then calling sudo we should be able to inject our own sudo exploit variant in through $PATH hijacking! Bam, attack vector identified.
Excellent, now all that is left is to get the root.txt flag! Right? Maybe?
I have to admit, this part of the box I did not appreciate. For as good as the user portion of working with smart-contracts was this last bit for the root.txt flag was very contrived. With that said I did expand my knowledge on the following technique and I cannot complain too much as ultimately that is the purpose of going through all this - to learn new concepts and reinforce old ones. This part was not extremely obvious, however the HTB forums did have one excellent hint - "Don't slack off". After a little bit of searching read a few good articles, including this one, where they explained firstly what slack space is and ultimately how to use it for hiding data.
Before going to explain slack space, one should know what blocks (on Linux) and clusters mean (on Windows). Blocks are specific sized containers used by file system to store data. Blocks can also be defined as the smallest pieces of data that a file system can use to store information. Files can consist of a single or multiple blocks/clusters in order to fulfill the size requirements of the file. When data is stored in these blocks two mutually exclusive conditions can occur; The block is completely full, or the block is partially full. If the block is completely full then the most optimal situation for the file system has occurred. If the block is only partially full then the area between the end of the file the end of the container is referred to as slack space
With theory understood found a few github repos for bmap. Unfortunately the first repo I cloned did not end up working properly, but quickly found this repo that did.
And just like that Chainsaw is in the books. Thanks folks, until next time!