Sunday, March 09, 2008

The Problem with Kerberos Delegation

So, as I've stated before, in doing research for our Directory Experts Conference presentation I got a "little hung up" on the whole security aspect of SharePoint and getting Kerberos to work. I need to understand why something doesn't work because that gives me insight into how it functions. I ended up with mixed results, and just when I thought I had things working and when I thought I had it all worked out it broke and I had to start from scratch. I started with the following very excellent breakdown of Kerberos Delegation:

These walkthroughs are very well detailed down to the netmon traces, but if you're starting out I recommend you keep it simple until you've got a better handle and then dive deep. My research inevitably led me here:

This was a bit more condensed but included a vital bit of knowledge I had not come across anywhere else:

In the case of Internet Explorer, the SPN requested is formed by using a service class of HTTP and a host as specified in the URL, converted to an FQDN (fully qualified domain name) if possible.

Here's the rub: IE never appends the port number to the host name when contacting the KDC for a ticket - even if your server is on a port other than port 80! So for all those SharePoint sites you have on non-80 ports, if you've been specifying a port number in your setspn command, then you haven't been using Kerberos!

WHAT!? I actually contacted James because my initial configuration appeared to be working despite James' warning but tinkering broke it and I was never able to reproduce my initial results. I then came across this KB article:

This confirmed what James was saying and what I was now experiencing but according to the KB article I had compliant versions of wininet.dll. Included in the KB article are instructions for creating a "feature" registry entry for Internet Explorer to enable the fix but doing so did not resolve the issue; that's when I turned to PSS.

The short version of the story with PSS is that the fix referenced in KB908209 isn't included by default in the versions of the service pack you're currently running. This has to do with two different code "paths" that Microsoft releases known as a GDR (General Distribution Release) and QFE (Quick Fix Engineering). The fix in question was released as QFE and when you do a "normal" install of a service pack or hotfix rollup you get the GDR version so adding the registry key does nothing. For XP SP2 you can install a recent IE security update like MS08-010 (KB944533) and apply the QFE version like so:

WindowsXP-KB944533-x86-ENU.exe /B:SP2QFE

In Windows XP Service Pack 3, this fix was moved into the GDR tree as well as in SP2 for Windows Server 2003, Vista RTM, and Windows Server 2008 RTM. If you are running any of these or better you have the fix included but you're still missing the registry key:



HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer
\Main\FeatureControl\FEATURE_INCLUDE_PORT_IN_SPN_KB908209
Dword: Iexplore.exe
Value: 0

Yes, you read correctly, you still need to manually create the registry key on all of your clients that intend to consume web applications via Kerberos authentication that utilize a non-standard port (anything other than port 80 or 443). My beef with PSS at the moment is that there are still no references other than the original KB article that talks about the key needing to be created but it's not clear that even in much more up to date version (including IE 7 or Windows Server 2008) you still have to create that blasted key.

An Easier Way?

Now, chances are that from a SharePoint perspective, the only sites you're accessing that have non-standard ports are ones for the Central Admin site. Few people if any, are actually deploying sites to their customers with non-standard ports, are they? How many of you are using an Internet proxy running on port 8080? If this is a box in the domain verifying your Active Directory credentials then you're using NTLM - plain and simple.

But...there is an easier way to deal with this. I only see two alternatives to creating the registry keys everywhere:

  1. Re-deploy everything using host headers and port 80 or 443, or
  2. Create SPN registrations for sites with non-standard ports both with and without the port

Both options have their merits - if you have more control over the environment from a standards perspective then I would lean towards the first option as it's cleaner and avoids the issue altogether. If you have less control or cannot use host headers then you're stuck with the second option which is going to require four SPN's for each service account hosting an application on a non-standard port instead of two.

Confused Yet?

Wait, it gets better - how many of you, when creating your host header went and registered it as a CNAME record in DNS? Want to know why your Kerberos delegation is STILL failing with "You are not authorized to view this page"? This is a habit for all of us really and we don't stop to think what a CNAME is really - it's an alias sure, but when DNS resolves it, it resolves to the name under the A record, i.e. the computer running the web server. Allow me to illustrate:

  • Computer running IIS: ws.identitychaos.com (WS)
  • Service Account hosting the Central Admin app pool: idchaos\svc.wss.farm
  • Host Header for Central Admin: spca.identitychaos.com
  • SPN's registered to idchaos\svc.wss.farm
    • HTTP/spca
    • HTTP/spca.identitychaos.com

Using a CNAME, when IE requests the SPN, spca.identitychaos.com resolves to ws.identitychaos.com (the alias resolves to the host) so IE asks AD, "tell me which account has an SPN registration of HTTP/ws.identitychaos.com" and it gets the WS computer account, not the service account. How do you fix it? You use A records instead of CNAME's. While there is a fix for this, I don't believe it's actually a bug - I think you need to accept the fact that you need to use A records instead.

Summary

Follow these "simple" rules for Kerberos delegation:

  • Use host headers whenever possible to avoid using non-standard ports, otherwise register the host both with and without the port to cover for the IE failure

  • Always use A records for your host headers, CNAME's do not work for Kerberos

  • Never use BUILTIN accounts like Local System or Network Service to run these app pools - it's fine for testing or a lab, but in production this requires you to delegate to the computer account and register SPN's there instead

  • Never register the same SPN more than once, duplicate SPN's will cause delegation to fail because a unique match cannot be found

  • Despite what you may have read, SPN's are case insensitive, so you can't get around the duplicate issue by varying case.

I don't buy into the "best practice" that Central Admin should always be on a non-standard port. That is security by obfuscation and not security by design and I think securing the site properly for your privileged administrative accounts with Kerberos is priority. Are you convinced yet that you need something to manage SPN registrations yet? Why do I care in the first place?

Stay tuned, the AzMan/ILM solution is coming...really...I promise!

2 comments:

rG0d (CISSP, GCIH, GEEK) said...

A Microsoft KB articles to help out here (I think this is fixed by default in IE7):

This one fixes XP to allow Kerberos to use a CNAME when contacting a remote host:
http://support.microsoft.com/kb/911149

Also, if you're trying to connect to a share using an alias, you'll need to do the below steps on the server side. Otherwise, the server service fails because it doesn't recognize \\alias\share as a shareable object. Here, you're essentially telling the server service that this system is known by (and allowable) as the specified list of alternate names. Here are the steps:

Start the registry editor (regedt32.exe)

Move to HEY_Local_Machine\System\CurrentControlSet\Services\LanmanServer\Parameters

From the Edit menu select "Add Value"
Set the type to REG_SZ is you want one extra name or REG_MULTI_SZ if you want more than one and enter a name of OptionalNames.
Click OK

You will then be prompted for a value. Enter the other name (or names if type REG_MULTI_SZ, one on each line) you want it to be known as and click OK.

Close the registry editor

Reboot the machine

Brad Turner said...

Thanks for the feedback - I'm aware of the CNAME fix but I personally think it's a mistake to apply it. You're not fixing something that is broken here as with the IE port query problem - this is DNS being DNS and this patch is altering how the OS and DNS interact which is a bad idea IMHO.

Post a Comment