Spat's WebLog (Steve Patrick)

When things go wrong...

"Kerberos delegation .. end to end" Part III

"Kerberos delegation .. end to end" Part III

  • Comments 7


When we last left off, we had just installed SQL.


Also my standard disclaimer for this series:


First off let me say that I am not a “SQL guy” nor am I an “IIS guy” .. I am primarily a platforms OS kinda guy.


However, I can wing my way  thru some of those two technologies.  This series of posts may not exactly follow best practices when it comes to SQL or IIS but it will definitely get you up and running.


You may be thinking,  there are already a ton of resources to show how to get this up and running. Simply use your favorite search engine and look for  ‘Kerberos delegation SQL’ and you will find dozens of HOW TO articles, blogs etc..


I am hoping that this one will differ in two ways. One, is that it is an exact step by step. Two, is that we will go into the WHY’s of  why we do certain actions to make it all work ( mostly from an OS authentication perspective ) .


OK – so back to when we left off.


After we had installed SQL  and  tried to connect from the client machine we got this  error:


Exception Details: System.Data.SqlClient.SqlException: Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'.


The IIS Server was connecting as anonymous due to the fact it could not impersonate Bob , or in kerberos terms it was not enabled for delegation.


More specifically  - “it” in the above sentence is the service account  domain\SVC_IISPool under which the web site was running as.


Let’s fix that. On the DC open the SVC_IISPool account and enable it for “trust this user for delegation” – don’t worry about all the other knobs and switches for now.




Once you do this, and grant Bob proper SQL rights to read the database, you should see the page come up OK as Bob.





Here is a list of some of the tools we will use to examine the transaction in more detail:.


  • Klist.exe
  • Kerbtray.exe
  • Wireshark
  • Netmon3
  • Netmon2



The reason I use all those different net sniffers is just because I like certain features from each one.


When it comes to delegation, states:


Multi-tier client/server applications present a special situation for the Kerberos protocol. In this kind of application, a client might connect to a server that must connect to a second server on the back end. For this to happen, the first server must have a session ticket to the second server. Ideally, this session ticket should limit the first server's access on the second server to what the client is authorized to do, rather than what the server is authorized to do.


The Kerberos protocol deals with this situation through a mechanism known as delegation of authentication . Essentially, the client delegates authentication to a server by telling the KDC that the server is authorized to represent the client.




Forwarded Tickets

If a client wants to delegate the task of obtaining session tickets for a back-end server to a front-end server, it must ask the KDC for a forwardable TGT. It does this through an AS Exchange by indicating to the KDC the name of the server that will act on the client's behalf. If Kerberos policy permits forwarding, the KDC creates a TGT for the front-end server to use in the client's name, sets the FORWARDABLE flag in the TGT, and sends the ticket back to the client. The client then forwards the TGT to the front-end server.


When the front-end server requests a session ticket to the back-end server, it presents the client's TGT to the KDC. When the KDC issues a session ticket for the back-end server, it sees the FORWARDABLE flag in the TGT, sets the FORWARDED flag in the session ticket for the requested server, and returns the session ticket to the front-end server. The option of setting the FORWARDED flag in a session ticket provides an added level of security because it permits administrators to configure individual servers to reject session tickets that have been forwarded.






The reason I highlighted the section in blue above - is because I have never actually seen it ( the blue part ) work this way ( read as , I think it is wrong unless someone can show me otherwise )


So let’s take a look at this.



Here is a link to the trace I am looking at below:


This trace is taken on the XP client as he opens the web page.




FRAME 11 and 12:

You can see the typical deny\negotiate HTTP packets – see  for more info on that.





We see the TGS request for the HTTP SPN..



The KDC responds with the TGS_REP

KERBEROS: Client name (cname[4]) =bob

KERBEROS: Server name (sname[2]) =HTTP/sp132027c.request132027.local



That's all the kerberos or authentication traffic we see   after that he get access to the web site.


We seem to be missing something. Where is the forwarded TGT to the IIS Server?


Does the IIS Server ask for the clients TGT? Let’s think about that.


In order to do so, he would need to know Bob’s password, which he does not – so this is not possible ( disregard any S4U thoughts here – we are talking straight unconstrained delegation here )


OK so if the IIS server does not ask for the TGT where is it – let’s look at the same requests from the KDC’s perspective.



See the previous link or the bottom of this post for the actual net traces.

This trace is taken on the KDC as the client opens the web page.






FRAME 30 and 31:

A TGS_REQ and response  from the XP machine to authenticate  to the HTTP service.

KERBEROS: Server name (sname[3]) =HTTP/sp132027c.request132027.local



A TGS_REP from the KDC in response to the TGS_REQ from the IIS Server for authentication to the SQL service. Note that the principal name ( authenticated as )  is Bob

KERBEROS: Principal name value (name-string[1]) =bob

KERBEROS: Server name (sname[2]) =MSSQLSvc/sp132027b.request132027.local:1433


For now , that is all we care about. How did we go from the client asking for HTTP to the IIS Server getting a successful TGS_REP  for Bob?




Let’s do a clean logon and see where we start off:


I am going to use a combination of 2 tools – klist.exe and kerbtray.exe.


As soon as we logon we can see our tickets via kerbtray.exe




Looks normal, we have our CIFS ( for the SMB connections we made for group policy ) , our LDAP ( for ldap requests )  and our krbtgt ( our TGT ). But why do we have 2 TGT’s?

Look at them closer via the flags tab.


k37   k38


Notice that one has the “forwarded” flag set.


One of them is the “delegation TGT” – or the one which we will pass on to other services when it is needed for delegation.



Can we prove this?


Use klist.exe to purge the tickets “klist purge” and then say yes to purge each one.


Now – look at another net trace when you open IE and go to the web site. See XP_trace2.cap in the file attached to this post.





We see quite a bit more than the first trace. ( remember the client only sent one TGS_REQ for HTTP ? )

This time we see the HTTP/1.1 401 Unauthorized, then some ldap and dns, and then an AS_REQ


FRAME 20\21

TGT request.

KERBEROS: Principal name value (name-string[1]) =bob

            KERBEROS: Server name (sname[3]) =krbtgt/REQUEST132027.LOCAL


Then we see two TGS_REQ’s


FRAME 22\23

TGS_REP data shows:

            KERBEROS: Principal name value (name-string[1]) =bob

            KERBEROS: Realm (realm[1]) =REQUEST132027.LOCAL

            KERBEROS: Server name (sname[2]) =HTTP/sp132027c.request132027.local



This is the TGS_REP

            KERBEROS: Principal name value (name-string[1]) =bob

            KERBEROS: Realm (realm[1]) =REQUEST132027.LOCAL

            KERBEROS: Server name (sname[2]) =krbtgt/REQUEST132027.LOCAL


Now that’s an odd TGS reply .. krbtgt?


Why isn’t it coming across as an AS_REQ?

In fact, this is a special TGS_REQ, it is a delegation TGT request, which is satisfied via a TGS request.


Look at the request ( frame 24 ) closer… note the “forwarded bit”  which is set. This would indicate that this is a request meant to be forwarded - or as netmon3 parsers put it “this is a request for forwarding.


            Forwarded:             (..1.............................) Indicates that this is a request for forwarding


KDCOptions: 60810010 (Forwardable, Forwarded, Renewable, Canonicalize, Renewable OK)





It is starting to make sense now.


·         Get a TGT via the  AS_REQ

·         Get  the  ticket for the HTTP service - HTTP/sp132027c.request132027.local

·         Get a delegation TGT - via the TGS_REQ ( fwd'd bit set )

·         Pass the delegation TGT on to the IIS Server

·         IIS Server requests MSSQLSvc/sp132027b.request132027.local:1433  as Bob


Also note the large HTTP packets which follow – we send 3 frames from the XP to IIS server

If we use wireshark to open this same trace and use Follow TCP stream we can easily see the conversation data







Then to put it all in context here is what we see:





HTTP/1.1 401 Unauthorized

Content-Length: 1656

Content-Type: text/html

Server: Microsoft-IIS/6.0

WWW-Authenticate: Negotiate

WWW-Authenticate: NTLM

X-Powered-By: ASP.NET

Date: Thu, 22 Nov 2007 00:17:18 GMT


<HTML><HEAD><TITLE>You are not authorized to view this page</TITLE>

<META HTTP-EQUIV="Content-Type" Content="text/html; charset=Windows-1252">

<STYLE type="text/css">

  BODY { font: 8pt/12pt verdana }

  H1 { font: 13pt/15pt verdana }

  H2 { font: 8pt/12pt verdana }

  A:link { color: red }

  A:visited { color: maroon }


</HEAD><BODY><TABLE width=500 border=0 cellspacing=10><TR><TD>

<h1>You are not authorized to view this page</h1>

You do not have permission to view this directory or page using the credentials that you supplied because your Web browser is sending a WWW-Authenticate header field that the Web server is not configured to ccept.


<p>Please try the following:</p>


li>Contact the Web site administrator if you believe you should be able to view this directory or page.</li>

<li>Click the <a href="javascript:location.reload()" mce_href="javascript:location.reload()">Refresh</a> button to try again with different credentials.</li>


<h2>HTTP Error 401.2 - Unauthorized: Access is denied due to server configuration.<br>Internet Information Services (IIS)</h2>


<p>Technical Information (for support personnel)</p>



Go to <a href="" mce_href="">Microsoft Product Support Services</a> and perform a title search for the words <b>HTTP</b> and <b>401</b>.</li>

<li>Open <b>IIS Help</b>, which is accessible in IIS Manager (inetmgr),

 and search for topics titled <b>About Security</b>, <b>Authentication</b>, and <b>About Custom Error Messages</b>.</li>




FRAME 20\21

TGT request.


KERBEROS: Principal name value (name-string[1]) =bob

            KERBEROS: Server name (sname[3]) =krbtgt/REQUEST132027.LOCAL





FRAME 22\23

TGS_REP data shows:


KERBEROS: Principal name value (name-string[1]) =bob

            KERBEROS: Realm (realm[1]) =REQUEST132027.LOCAL

            KERBEROS: Server name (sname[2]) =HTTP/sp132027c.request132027.local



KDCOptions: 40810000 (Forwardable, Renewable, Canonicalize)

This is the TGS_REP


KERBEROS: Principal name value (name-string[1]) =bob

            KERBEROS: Realm (realm[1]) =REQUEST132027.LOCAL

            KERBEROS: Server name (sname[2]) =krbtgt/REQUEST132027.LOCAL


FRAME 26,27,28


GET / HTTP/1.1

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, */*

Accept-Language: en-us

UA-CPU: x86

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727)

Host: sp132027c

Connection: Keep-Alive


































Frames 26,27,28 are the HTTP get requests, which include the Kerberos data.


In Kerberos terms – this is the AP_REQ. We include the data from the TGS_REQ for HTTP as well as the delegationTGT in this data.


Wheww .. OK so now we know how the basics of delegation work. The client code will call InitializeSecurityContext and pass ISC_REQ_DELEGATE if you want a breakpoint there in IE.


As you probably know, this form of delegation is not secured against malicious use by the server or the SVC_IISPool account. In fact, now that this service has Bob’s TGT he can do most anything with it.


This brings up constrained delegation and something we call S4U.


Next up – constrained delegation details.






Leave a Comment
  • Please add 2 and 3 and type the answer here:
  • Post
  • I enjoy these deep dives immensely. Looking forward too constrained delegation.

    Keep up the good work!


  • So...when we'll have a pleasure to read "Part IV" :)?

  • Hopefully part 5 will be "getting this all to work with NLB" ;)  Which is the piece I am currently having issues with.

  • Last week, I spent an all-nighter troubleshooting a Kerberos issue for a MOSS installation. Although

  • So much information to digest - thank you!. We are running into this issue intermittantly (Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'). The App pool is configured to use Network Service so in your example above you gave permissions for delegation to the service running your app pool (SVC_IISPool) - there is no specific "Network Service" user to configure. We added delegation to the IIS Server itself to be able to delegate the MSSQLSvc on the database server. Like I said, it's intermittant - one minute it's working, then next it is not! Any tips to trap and correct this behavior?

  • did you enable the kerberos logging I outlined?

    That - and a network sniff ( if you can get one ) will be really helpful.

    Also we want to see the security audit logs to track where the logon worked and or failed as the end user.

  • GmOVcL  <a href="">mjegmczqtdao</a>, [url=]wbswjutneggk[/url], [link=]hoblelmmtekq[/link],

Page 1 of 1 (7 items)