Breaking

How to test Kerberos authenticated web applications?

First of all: This is not an in-depth Kerberos how-to, nor is this tutorial about the different aspects of web application testing. This tutorial is just to give support in testing Kerberos authenticated web applications. The goal is to hand over the right tools and steps to be able to perform the configuration and be able to test the application.

When to use it?
When there is a 401 server response with the header “WWW-Authenticate: Negotiate”. This can either mean Kerberos or NTLM authentication is needed. It is possible to distinguish them by looking at valid authenticated client traffic. As a simple reminder: The NTLM Authorization header will always start with the value “TlRM…”, the Kerberos Authorization header will always start with “YII…”. For further information this link is recommend.
In this tutorial the term “Kerberos authentication” will be used. There are other terms sometimes used like SPNEGO, SSO or integrated authentication.

What Software is needed?
First of all a Kerberos implementation that is able to talk to the KDC (Key Distribution Center) is needed. The python based proxy “proxpy” will be used as the outgoing proxy. Furthermore, the python library PyKerberos will be used.

Gather the information about the domain
To be able to write the Kerberos configuration, first of all, the information needs to be extracted form a Microsoft Windows domain member. There are many different ways to get this information; only one of the possibilities via the command line is shown here.
First the domain name is necessary. This can be acquired by running “systeminfo”.

C:\Users\username>systeminfo
[...]
Domain: example.com
[...]

 

Since the domain name is known, it is possible to use nltest to query the domain for further information.

C:\Users\username>nltest /dsgetdc:example.com
           DC: \\kdc.example.com
      Address: \\10.0.0.1
     Dom Guid: 00000000-0000-0000-0000-000000000000
     Dom Name: example.com
  Forest Name: example.com
 Dc Site Name: Default-First-Site-Name
Our Site Name: Default-First-Site-Name
        Flags: PDC DS LDAP KDC TIMESERV WRITABLE DNS_DC DNS_DOMAIN DNS_FOREST CL
OSE_SITE FULL_SECRET WS
The command completed successfully

 

Kerberos configuration
After gathering the necessary information, it is now possible to write the Kerberos configuration. A sample configuration could look like this:

>cat /etc/krb5.conf

[logging]
        Default = FILE:/var/log/krb5.log

[libdefaults]
        ticket_lifetime = 24h
        clock-skew = 300
        default_realm = EXAMPLE.COM
        dns_lookup_realm = false
        dns_lookup_kdc = false
        forwardable = true
        renew_lifetime = 7d

[realms]
        EXAMPLE.COM = {
        kdc = kdc.example.com:88
        admin_server = ad.example.com:464

}

[domain_realm]
        .example.com = EXAMPLE.COM
        example.com = EXAMPLE.COM

For further information see the krb5 documentation

Kerberos commands
After writing the Kerberos configuration, it is necessary to test it. For this purpose kinit is used. kinit is used to obtain and cache Kerberos ticket-granting tickets. A valid set of domain credentials is needed to authenticate against the KDC.

>kinit username@EXAMPLE.COM
Password:

 

To view the local ticket cache after successful authentication, klist is used.

>klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: username@EXAMPLE.COM

Valid starting Expires Service principal
12/06/2015 10:24:50 12/06/2015 20:24:50 krbtgt/EXAMPLE.COM@EXAMPLE.COM
        renew until 12/13/2015 10:24:46

 

The output shows that there is currently one Kerberos ticket-granting ticket (krbtgt).
To delete all tickets kdestory can be used without options.

>kdestroy

 

Using Firefox to test the current settings
At this point it is possible to use e.g. Mozilla Firefox to visit the Kerberos authenticated web application. To configure Firefox it is necessary to go to about:config and search for negotiate

network.negotiate-auth.delegation-uris set to .example.com
network.negotiate-auth.trusted-uris set to .example.com

After this configuration step, Firefox can authenticate against the web application.

Kerberos Proxy

For this step there should be a working Kerberos configuration and a valid TGT. Then from this point on, all that is needed is a proxy that adds a Kerberos ticket into the HTTP header on every authentication failure. The tool proxpy with an own Kerberos plugin will be used. The plugin code looks as follows and is pretty self-explanatory.

>cat plugins/kerberos.py
def proxy_mangle_request(req):
    v = req.getHeader("Host")
    if len(v) > 0 and "example.com" in v[0]:
        import kerberos
        __, krb_context = kerberos.authGSSClientInit("HTTP@www.example.com")
        kerberos.authGSSClientStep(krb_context, "")
        negotiate_details = kerberos.authGSSClientResponse(krb_context)
        req.addHeader("Authorization", "Negotiate " + negotiate_details)
    return req

 

To start the proxpy use a command line similar to this:

>python2.7 proxpy.py -a 127.0.0.1 -p 3128 -vvv -x plugins/kerberos.py

 

After using the web application (either with Firefox or with the proxy), the ticket cache looks as follows

>klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: username@EXAMPLE.COM

Valid starting Expires Service principal
12/06/2015 10:24:50 12/06/2015 20:24:50 krbtgt/EXAMPLE.COM@EXAMPLE.COM
        renew until 12/13/2015 10:24:46
12/06/2015 10:51:15 12/06/2015 20:24:50 HTTP/www.example.com@EXAMPLE.COM
        renew until 12/13/2015 10:24:46

 

Everything works as expected and the common tools can be used. proxpy just needs to be setup as the last proxy to ensure every request gets authenticated.
Happy testing of Kerberos authenticated web applications.

Kind Regards,
Simon