Today Active Directory Security has become mission-critical to organizational security worldwide and thus mission-critical to Cyber Security worldwide. On this blog, former Microsoft Program Manager for Active Directory Security, and today, CEO of Paramount Defenses, shares valuable technical insights on Active Directory Security.

Gold Finger The Paramount Brief Gold Finger Mini World Peace

Tuesday, May 27, 2014

Kerberos Token Bloat - Details, Example, Token Size Calculation Tools and Security Implications


My apologies for the continued delay in sharing insights. As the CEO of a $B cyber security company that has customers in 6 continents, time has become my biggest constraint. However, this week onwards, I plan to share something valuable every week.

Although we’re primarily focused on helping organizations worldwide address the world’s top cyber security risk, we often get requests from organizations to assist with related issues. A few weeks ago, a world famous Swiss bank reached out to us requesting our assistance in helping them efficiently address the issue of KerberosToken Bloat. (And help them we did.)

The issue of Kerberos Token Bloat potentially impacts the security of every organization running on Active Directory, and thus is worth addressing. So, today, I was determined to take out some time and share a few thoughts with you on this topic.

[NOTE - If you’re short of time, and are looking for an easy/automated way to correctly determine the token size of any/all domain user accounts in your Active Directory, you can skip to the second-last section of this post, or click here.]

The Crux of the Issue

There appear to be many sources of information on this topic online, and many re-hashed blogs, but not too many sources that provide a sufficiently deep technical explanation, so this is my humble attempt to do so. 
  • Disclaimer: Kindly note that my core expertise is in Active Directory Security, not in the inner workings of every detailed aspect of Windows Security (which, like the field of medicine, is an ocean of a subject), such as the inner workings of the Kerberos SSP, and I only had 30 minutes to devote to this blog entry, so the Crux session is a best-effort basis presentation put together within the given time constraint.

Full details on this topic could take an entire chapter in a book. However, in the interest of time, I'll attempt to share its crux -

In Microsoft Windows Server environments, the Microsoft Security Services Provider Interface (SSPI) is the foundation of authentication. It lets applications use any of the available security packages without changing the interface to use security services. It also provides a mechanism to carry opaque authentication tokens over the existing communication channel between the client and server. Each network protocol, including Kerberos, is provided in the form of a Security Service Provider (SSP) and the 5 default SSPs in Windows Server - Negotiate (SPNEGO), Kerberos, NTLM, Schannel, and Digest authentication protocols, are all plugged into the SSPI in the form of DLLs.

When two parties (client and server) require authentication for secure communication, their requests for authentication are routed to the SSPI, which completes the authentication process, regardless of the network protocol currently in use. However, before the two parties can use SSPI, they must agree on the security package they wish to use. Once the two parties have agreed on a security package, they can use the SSPI API to establish network authentication.

Most of the SSPI functions have variable length arguments for the caller (application) to provide message data to the security package and for the security package to return security data to the caller.  For example, the caller can use security buffers to pass message data to the security package, or to receive an output security token from the security package.
Security buffers can be passed in as an array of buffers. The security buffer descriptor identifies the number of buffers and the starting address of the buffer array. Each security buffer also has a buffer type field to identify the contents of the buffer.

Each time a security API is called that takes a SecBufferDesc parameter, it should be setup with one or more SecBuffers. For example, there can be two security buffers, one that contains input message data and the other for the output opaque security token returned by the security package. The order of security buffers in the security buffer descriptor is not important, but they should be tagged with the appropriate type.
However, the size of the output buffer that is expected to contain the security token is important.
The caller (application) determines the maximum token size for a security package during initial setup by calling the QuerySecurityPackageInfo() function for a specific security package, and using the returned cbMaxToken value.
It is based on this value that the application then initializes the buffer pointers and sizes in the buffer description.
NOW, as you may know, the default maximum token size for the Kerberos authentication package (i.e. Kerberos SSP) was 8000 bytes in Windows 2000 and is 12,000 bytes in Windows Server 2003/8.
As a result, when the caller (application) calls QuerySecurityPackageInfo() function to determine the maximum token size for the Kerberos package, the cbMaxToken value that is returned to the user is 8000 bytes in Windows 2000 and 12,000 bytes in Windows Server 2003/8. It is based on this return value that the caller initializes buffer pointers and sizes.
The client and server then each call AcquireCredentialsHandle(), following which the client calls InitializeSecurityContext() and the server calls AcquireSecurityContext(). Under the hood, the Kerberos SSP on the client's machine takes care of requesting a session ticket from the KDC and sending it across to the server, and the Kerberos SSP on the server's machine takes care of receiving and decrypting the ticket. If all's well thus far, the server can then call ImpersonateSecurityContext().
Under the hood, during the above, when the KDC receives the session ticket request, it generates and inserts the list of SIDS of all the global, universal and domain local security groups that the user is a member of directly or indirectly, (plus SIDHistory) in the user's Privilege Attribute Certificate (PAC),  which is stored in the Authorization-Data (Optional) field of the service ticket that the KDC issues to the client for submission to the server. (As you may know, strictly speaking, it copies the PAC from the client's TGT into the service ticket's PAC, then adds the list of all DLGs to which the user directly or indirectly belongs, to it.)
Then, at the server side, when the Kerberos SSP receives and decrypts the service ticket, it verifies/validates the PAC and then generates and return an output security token via the output buffer that was initialized and provided by the caller (application).
Now, remember that the size of this output buffer was based on the value of the maximum token size provided to the caller when it called the QuerySecurityPackageInfo() function to query the cbMaxToken size for the Kerberos package.
If the user belongs to a large enough number of groups, the amount of memory needed for the output security token (containing the SIDs of all the security groups to which the user belongs) will exceed the amount of space allocated for the output buffer, and thus the authentication request will fail, and as a result, the user will not be able to successfully logon.
In essence, the crux of the issue is that the amount of memory (default maximum token size) that the caller ends up allocating for the output buffer could be insufficient to hold the resulting output security token when the number of SIDs is large enough, and this can cause the authentication request to fail, resulting in a logon failure.

An Example of Kerberos Token Bloat

This issue is perhaps best illustrated with an example, so I’ll share an example with you which covers 2 scenarios –
  1. A domain user account holder U from domain A logs to a machine Ma, wherein this machine Ma also belongs to the domain A (i.e. is domain-joined to domain A)
  2. This same user U then proceeds to use a client-server application with the server component hosted on a machine Mb, wherein machine Mb is domain-joined to domain B
Scenario 1: Interactive Logon to a machine on Domain A
Here is (roughly) what happens when domain user account A attempts to interactively logon to domain-joined machine Ma–  
  1. Domain user account holder U invokes the Secure Attention Sequence (SAS) on the machine by pressing Alt-Ctrl-Del.
  2. Upon invocation of the SAS, Winlogon switches to the logon desktop, and dispatches GINA to collect the logon data.
  3. GINA collects and returns the user’s logon data to Winlogon, which then sends the data to the LSA by calling LsaLogonUser.
  4. The LSA immediately converts user’s plaintext password to a secret key by passing it through a one-way hashing function.
  5. The LSA then creates pre-authentication data by encrypting a timestamp with the secret key derived from the user’s password.
  6. The LSA then invokes the Kerberos SSP and sends a KRB_AS_REQ message (which includes this pre-authentication data) to the user’s KDC authentication service.
  7. The KDC’s authentication service uses the user’s identity (UPN) contained in the KRB_AS_REQ to locate the user in its account database (Active Directory).
  8. The KDC then uses the account’s hashed password to attempt to decrypt the pre-authentication data.
  9. If the KDC is able to successfully decrypt the pre-authentication data, it then proceeds to evaluate the timestamp. If the timestamp passes the test, the KDC can authenticate the user.
  10. If the user is authenticated, the KDC then identifies all the universal and global groups to which the user belongs (directly or indirectly) and packages them in a PAC.
  11. The KDC then builds a TGT for the user, inserts this PAC in it, and replies back with a KRB_AS_REP message, which includes this TGT for the user.
  12. The LSA then sends a KRB_TGS_REQ message to the KDC’s ticket-granting service to request a session ticket for the user for admission to this computer.
  13. Since this computer belongs to the same domain, the KDC then identifies all the domain local security groups (in this domain) to which the user belongs (directly or indirectly.)
  14. It then copies the data from the PAC stored in the TGT into a new PAC created for this session ticket, and it adds all the identified domain local security groups to this PAC.
  15. It then creates a service ticket good for admission to this computer, inserts the new PAC in it, and replies back with a KRB_TGS_REP message, which contains this service ticket.
  16. Upon receipt of the user’s session ticket for this computer, the LSA decrypts it with the computer’s secret key, and extracts the PAC (which contains the user’s authorization data.)
  17. It then queries the local Security Accounts Manager (SAM) database to determine if the user is a member of any machine local security groups (directly or indirectly.)
  18. If it finds any local security groups that the user might be a member of, it then adds this list of groups taken from the PAC.
  19. It then creates an access token for this user and passes it back to Winlogon. (Technically it creates a logon session, and the access token is associated with the logon session.)
  20. Winlogon then creates a window station and several desktop objects, attaches the user’s access token, and starts the shell process designated for this user.
The user’s access token is subsequently inherited by any application process that he starts during the logon session.

The key points to note here are that during the creation of the PAC for the session ticket –
  1. The Global and Universal Group memberships were taken from the PAC in the TGT
  2. Only those Domain Local Groups that belong to the computer’s domain (and of which the user is a member directly or indirectly) were included.
Now, let’s assume that the user was a member of 10 universal groups, 15 global groups and 25 domain local groups from the computer’s domain (which in this case is the same as the user’s domain).
In this case, the PAC in this Session Ticket contained 50 security groups in all, and that the resulting Kerberos token size would have been approximately 1200 + (40*25) + (8*(15+10)) bytes = 2400 bytes, based on Microsoft's recommended formula, details of which are provided below.
Since 2400 bytes is well below the 12000 byte MaxTokenSize limit, the user did not experience any issues with the logon.
Scenario 2: Network logon to a machine on Domain B

Now let us assume that immediately after logging on, the user U launches the client side of a client-server application, the server side of which is running on a domain joined machine Mb in domain B (i.e. the machine is joined to the domain B.)

Assume that this client-server application use SSPI for network authentication, prefer to use Kerberos, and that the client knows the SPN of the server-side of the application.

Here is (roughly) what happens under the hood in this scenario –
  1. The user launches the client side of the application.
  2. The client side of the application establishes a socket connection with the server
  3. The client and server sides each proceed to call QuerySecurityPackageInfo() to determine the max token size for Kerberos
  4. Then the client and server sides each proceed to call AcquireCredentialsHandle() passing in the name of the Kerberos package, to acquire a handle to their pre-existing credentials
  5. Then, the client calls InitializeSecurityContext() to give the SSP a chance to prepare an outgoing token (; this token is not to be confused with a “Windows access token”)
  6. The client then transmits the resulting token to the server
  7. When the server receives this token, it calls AcceptSecurityContext() to pass the token to its SSP. (This function may be called two times.)
  8. Upon a successful final pass of the AcceptSecurityContext() function on the server side, the system will generate a new network logon session for the client (i.e. the user)
  9. The server-side will then call ImpersonateSecurityContext() to ask the SSP to place a token for the client’s logon session (on the server)
  10. Finally when done, the server-side will call RevertSecurityContext() to discontinue the impersonation of the caller
Now, in case you find yourself wondering where the necessary Kerberos related exchanges are in the description above, the answer is that they are automatically handled by the SSP between steps 5 – 8 above since the SSP abstracts protocol specific details.

As it pertains to Kerberos, here’s (roughly) what happens under the hood between steps 5 through 8 above –
  1. The client sends a KRB_TGS_REQ to the client’s KDC client, presenting its TGT, an authenticator, and the name of the target server (the Server Principal Name or SPN.)
  2. The client’s KDC uses the SPN to determine that it is belongs to another realm, so it creates a TGT that the client can submit to a KDC in the server’s domain for requesting the service ticket
  3. Before returning this TGT to the user, the KDC copies the PAC from the initial TGT into this TGT
  4. The client then sends a KRB_TGS_REQ to the server’s KDC, presenting the new TGT, an authenticator, and the name of the target server (the Server Principal Name or SPN.)
  5. The server’s KDC verifies the TGT (since it was signed by the client’s KDC, and these two Kerberos realm KDCs trust each other) and proceeds to generate a service ticket to the client for the server
  6. Prior to the generation of the service ticket, the server’s KDC identifies all the domain local security groups from the server’s domain to which the user belongs (directly or indirectly.)
  7. It then copies the data from the PAC stored in the presented TGT into a new PAC created for this session ticket, and it adds all the domain local security groups identified above to this PAC.
  8. It then creates a service ticket good for admission to the server, inserts this new PAC in it, and replies back with a KRB_TGS_REP message, which contains this service ticket.
  9. Upon receipt of the user’s session ticket for the server, the client sends a KRB_AP_REQ message along with the ticket and a new authenticator, to the target server, requesting access.
  10. The server decrypts the ticket, validates the authenticator, and and extracts the PAC (which contains the user’s authorization data.)
  11. It then queries the local Security Accounts Manager (SAM) database to determine if the user is a member of any machine local security groups (directly or indirectly.)
  12. If it finds any local security groups that the user might be a member of, it then adds this list of groups taken from the PAC.
  13. It then creates an access token for this user. (Technically it creates a network logon session, and the access token is associated with this network logon session.)
Now, above we had assumed that the user was a member of 10 universal groups, 15 global groups and 25 domain local groups from the user’s domain (which in this case is the same as the user’s domain).

Now, let us also assume that this user also happens to be a member of 300 domain local security groups in the server’s domain.

In this case, the PAC in this Session Ticket will contain 325 security groups in all, and the resulting Kerberos token size would be approximately 1200 + (40*300) + (8*(15 + 10)) bytes = 13500 bytes.

Since 13500 bytes is above the 12000 byte MaxTokenSize limit, the user will actually not be able to logon and the Kerberos SSP will most likely throw an error during the AcceptSecurityContext() call on the server.

The end result will be that the user will not be able to successfully authenticate to the server, and if this server was running Windows Server 2008, you might see the following message in the Kerberos event log –

Event Details
Product: Windows Operating System
ID: 6
Source: Microsoft-Windows-Security-Kerberos
Version: 6.0
The Kerberos SSPI package generated an output token of size 34BC bytes, which was too large to fit in the token buffer of size 2EE0 bytes, provided by process id 0. The output SSPI token being too large is probably the result of the user U being a member of a large number of groups.It is recommended to minimize the number of groups a user belongs to. If the problem can not be corrected by reduction of the group memberships of this user, please contact your system administrator to increase the maximum token size, which in term is configured machine-wide via the following registry value: HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters\MaxTokenSize.

Potentially Impacted Services in Windows

It is worth noting that in a Microsoft Windows Server environment, many distributed services use SSPI to access the Kerberos protocol. Here is a partial list of the various ways in which the Kerberos protocol is used for authentication -
  • Print spooler services
  • CIFS/SMB remote file access
  • LDAP queries to the Active Directory
  • Distributed file system management and referrals
  • IPsec host-to-host security authority authentication
  • Reservation requests for network Quality of Service
  • Intranet authentication to Internet Information Services
  • Remote server or workstation management using authenticated RPC
  • Certificate requests to Certificate Services for domain users and computers

Increasing the Size via the MaxTokenSize Registry Key

When Windows 2000 initially came out, the maximum size of a Kerberos authentication package specific token was hard-coded to be 8000 bytes in the RTM version of Windows 2000. It appears that way back in 2001 (see this KB and FAQ on same page), Microsoft released a Hotfix, which allowed admins to increase this value, based on a registry key called MaxTokenSize -
Although this value is theoretically configurable to a value up to 65535 bytes, practically, it is recommended not to exceed 48000 bytes  because of HTTP’s base64 encoding of authentication context tokens. (Finally, there are also issues reported when IT personnel accidentally set the value to 65535 Hex, instead of 65535 decimal.)

 Today, the default maximum size of a Kerberos authentication package specific token is 12000 bytes in Windows Server 2003 and Windows Server 2008, and 48,000 bytes in Windows Server 2012.

Microsoft has also provided efficient ways to add this Registry key to mulitple computers in a domain. Options include a GPO based ADM file application in Windows Server 2003, using the Registry client-side extension in Windows 2008 and using a newly defined GPO setting (see below) in Windows Server 2012.

Set maximum Kerberos SSPI context token buffer size

In Windows Server 2012 and in Windows 8, Microsoft has introduced a new GPO to help make it easy to have this registry key be set on multiple computers. This new setting is under System > Kerberos, and it is called titled Set maximum Kerberos SSPI context token buffer size -

The description of this setting reads -

"This policy setting allows you to set the value returned to applications which request the maximum size of the SSPI context token buffer size. The size of the context token buffer determines the maximum size of SSPI context tokens an application expects and allocates. Depending upon authentication request processing and group memberships, the buffer might be smaller than the actual size of the SSPI context token. If you enable this policy setting, the Kerberos client or server uses the configured value, or the locally allowed maximum value, whichever is smaller. If you disable or do not configure this policy setting, the Kerberos client or server uses the locally configured value or the default value."

(This is in line with the crux of the issue described above.)

Microsoft's Recommendations for Token Size Calculation

In order to help organizations address this issue, Microsoft provides the following formula to help determine the maximum token size of a given domain user account -

     Token Size = 1200 + 40d + 8s

     This formula uses the following values:

  • d: The number of domain local groups a user is a member of plus the number of universal groups outside the user's account domain that the user is a member of plus the number of groups represented in security ID (SID) history.
  • s: The number of security global groups that a user is a member of plus the number of universal groups in a user's account domain that the user is a member of.
  • 1200: The estimated value for ticket overhead. This value can vary, depending on factors such as DNS domain name length, client name, and other factors.

(This is a verbatim quote from the “More Information” section of the Microsoft Knowledge Base article 327825)
1015 Groups - Another Related Limitation
I'll digress for 30 seconds.
Based solely on the formula above, it might be possible for a user to be a member of say 2500 global groups and yet be able to logon (assuming an increased token size of 48000 bytes.) However, there is one other system limitation in Windows that will prevent this user from logging on, which is as follows.
In Windows, the maximum number of security identifiers (SIDs) that can be contained in a user's Windows access token is 1024. Now, assuming that the LSA can add upto 9 SIDs representing the type of logon etc, the realistic maximum limit is 1015.
Thus, irrespective of the token size calculations, the maximum number of groups that a user can be a member of is 1015.
End of digression.

A Small Ambiguity in Microsoft's Formula
This might sound obvious to many, but it is nonetheless worth mentioning and noting that when calculating the value of the variable d in the above mentioned formula, in regards to the number of domain local groups, it is important to understand that only those domain local groups that belong to the same domain as does the target server/resource and to which the user directly or indirectly belongs, need to be taken into account.
Here's why -
  1. An access token generated for a domain user account on a domain-joined machine, is always specific to the machine’s domain and to the machine, and
  2. An access token generated for a domain user account on a domain-joined machine, will only contain those DLGs that belong to the machine’s domain
I felt the need to share this because in our experience at Paramount Defenses, our Security Specialists have seen many instances wherein, in a multi-domain environment, IT administrators would take into account domain local groups from all domains, not just the target domain, thus incorrectly calculating this value.
Similarly, it is equally important to ensure that one also does not add global groups from any domain other than the user's domain, because a given domain user account can only be a member of global groups that belong to his own domain.
(Again, for many of you this might be obvious, but I'm told there's at least one script out there that may be adding global groups from other domains as well, thus potentially delivering inaccurate results.)
Existing Tools/Scripts to Calculate Token Sizes
There are 3 primary tools/scrips that seem to be in prevalant use -
  1. Tokensz - A free command-line tool provided by Microsoft
  2. CheckMaxTokenSize - A free script put together by a Microsoft employee
  3. Get-TokenSizeReport - A free script derived from CheckMaxTokenSize by an independent consultant
(I commend the developers of these scripts for the efforts they have put in to develop these scripts.)     

Here are some relevant details -

Tokensz is a free command-line tool provided by Microsoft that seems to be designed to assist organizations in simulating authentication requests and reporting the size of the resulting token.for a given account to a given service.

It offers various options, the main one being /compute_tokensize, which uses the SSPI functions InitializeSecurityContext() / AcceptSecurityContext() to compute the maximum token size for a given user. (In nearly all cases, the maximum token size is determined by the first call to InitializeSecurityContext().)

However, in order to compute the Token Size for a given domain user account, the tool needs to be run in the user's context i.e. either by the user, or with the knowledge of the user's password. One alternative is to embed it in a logon script, and then have the output for each user be output to a specific location, and then collect, assemble, and collate the data for each user to arrive at the token size list for multiple user accounts. In essence, it can definitely help determine token sizes but it requires a fair amount of additional work to put results for all domain user accounts together.

CheckMaxTokenSize is a free script put together by a Microsoft employee (and I'm assuming) with the intention of helping organizations determine the token size for a given user, by querying the Active Directory for all relevant group memberships for the given user and using Microsoft's recommended formula to arrive at an approximate token size for a given user. While the script seems to fulfill a real need for many organizations, it does require that it be run in the user context and that it can only be run interactively. In other words, an IT admin can send the script to the user, requesting him to run the tool and send the results back to the admin. It is very nice to see a Microsoft employee demonstrate the passion that makes Microsoft the great company that it is, in his personal efforts to help folks.

Get-TokenSizeReport is a script derived from the CheckMaxTokenSize script and put together by an independent consultant (and I'm assuming) with the intention of making it a little easier to run it on multiple user accounts. While it seems to be very popular, one of the drawbacks seems to be that, as mentioned above, based on its description, it appears that it may possibly be including groups that do not need to be included (e.g. global groups from all domains) and thus that its results may not be reflecting the real picture. (I do not know if there are other factors that may have been unintentionally be included as well, so I cannot comment on its accuracy without a thorough review of the code, but unfortunately I don't have time to do so.) I do however commend its author for putting in considerable time and effort to try and make this easier for everyone.
The one other thing to keep in mind about the CheckMaxTokenSize script, is that Microsoft views it as a sample script, and thus provides it with the following disclaimer -
  • "The sample scripts are not supported under any Microsoft standard support program or service. The sample scripts are provided AS IS without warranty of any kind. Microsoft further disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages."

In other words, you're welcome to use it at your own risk.

A Professional, Automated Multiple Domain User Acccount Token Size Calculator
As I had indicated above, one of the reasons I made the time to write this blog entry is because a few weeks ago, a world famous Swiss bank had reached out to us requesting our assistance in helping them effiiciently address this issue.

This issue was important for them, and they were hesitant to rely on scripts to address this problem. (Apparently one of the main concerns they had with scripts is that they were worried that anyone with sufficient write-access to the script file could modify it either unintentionally or intentionally thus compromising its integrity.) They also did not want to go through the laborious exercise of having to deploy Tokensz as a logon-script via GPO, then collect and collate the results to get all the data.

Here is the essence of their requirements -
  1. We need to be able to calculate the maximum token size of multiple domain user accounts
  2. We need to be able to compute domain-specific token sizes, since we have multiple domains
  3. We do not wish to ask the user to run a script, or use a logon script to output results
  4. The approach should not require administrative access to run, or the requirement to be run on a DC
  5. The approach should be based on Microsoft's recommended formula (Token Size = 1200 + 40d = 8s)
  6. The approach should allow us the ability to control the accounts on which it is run (via an LDAP filter)
  7. We should be able to have the results in a CSV file so that our IT personnel can perform their analysis
  8. It would be nice to have a breakdown of the various group types that show up in a user's token
  9. Ideally, the solution should require zero to minimal extra work to be done by our IT staff
  10. Most importantly, the code of the solution should not be tamperable 

Although, as a company, we're focused on helping organizations worldwide solve a problem that's substantially more critical than this one, we decided to help them fulfill this requirement, because we felt that a vast majority of organizations could benefit from such a solution.

I am glad to report that our Engineering teams were able to successfully build a solution that delivered on all their requirements, and in fact we were able to add this capability to Gold Finger by simply adding a new report to its Token Viewer capability -  

Kerberos Token Size Calculator Tool
As displayed above, Gold Finger now also offers the world's first professional-grade, fully-automated, multiple domain user account Kerberos Token Size Calculator, and makes the challenge of trying to calculate Kerberos token sizes for all domain user accounts, as easy as touching a button.

Here are some details -
  1. It fully automates the calculation of token sizes for multiple domain user accounts
  2. It lets you calculate both domain and target-type (Member Server/DC) specific token sizes
  3. It lets you specify the set of domain user accounts you wish to focus on via application of LDAP filters
  4. It provides you a complete breakdown of the various groups contained in each user's token
  5. It calculates token sizes based on Microsoft's recommended formula (Token Size = 1200 + 40d = 8s)
  6. It even shows you the d and s values, as well as which group types contribute to which value
  7. It correctly includes all relevant security group memberships (e.g. domain local group memberships)
  8. It can run in the security context of any domain user account; no admin privileges needed to run
  9. It lets you export the entire output of the assessment to a CSV file
  10. Its integrity is protected by state-of-the-art anti-tampering measures as well as digital signatures
A sample CSV output file for Domain-Controller specific access tokens can be found here.

We believe that this can help thousands of organizations worldwide easily, efficiently and reliably address this vital problem, and save IT personnel worldwide hundreds of hours of laborious, detail-oriented and error-prone work, thus helping them to focus on their core responsibilities and providing organizations a reliable way to solve this problem.

Should you wish to learn more, the details can be found here.

Security Ramifications of Kerberos Token Bloat

The main reason I wanted to blog about  this is to help folks understand the security ramifications of Kerberos Token Bloat. If you give it due thought, you'll see that this is an issue that potentially impacts organizations of all sizes.

From a security perspective, the main point here is that this issue can result in a Denial-of-Service (DoS) for the impacted user. In most cases, this DoS could be caused by the fact that the user is actually a member of a large number of groups, and that is scenario that most organizations currently deal with.

However, it is also possible for a malicious insider (or an outsider who can gain control of specific machines) to very quickly launch a domain-wide denial-of-service attack against all or a targeted set of domain user accounts. To do so, all the malicious insider would have to do is create a large enough number of groups, make one a member of the other, an then add a group like Domain Users to the last group (or say in a targeted attack, add a group such as "Executive Users".) 

This would easily cause the targeted users to experience denial-of-service, and though IT personnel will ultimately be able to figure out what happened, the DoS attack could last long enough to cause potentially material damage. (For instance, hours before a public organization's earnings call, the entire Finance team could be prevented from logging on for hours, thus resulting in a situation where in key executives like the CFO may not be able to logon and thus send email, or access vital documents during those few critical hours.)

Of course, if someone were to target a Domain Controller's account, things could get ugly very quickly.

Now, the reason this impacts organizations of all sizes, is that, even in a small organization with only a handful of groups, someone could maliciously create a large number of security groups and launch an attack impacting all the domain user accounts in the domain, even though the number of domain user accounts is relatively small.

In other words, a small $500M publicly traded company with just a 100 employees is equally susceptible to being a victim in such an attack.

It also helps to keep in mind the smart attackers seldom carry out the attack in real-time. Instead, they'll just script the attack, and have it scheduled to run at some pre-determined time in the future. So while auditing might catch such an attack in progress, its source could very well be a (semi-)privileged service account running on some domain-joined machine, making it very difficult to catch the real perpetrator.

Thus, at an absolute minimum, it is very important for organizations to have precise answers to at least 4 questions at all times -
  1. Who can create security group memberships?
  2. Who can modify existing group memberships?
  3. Who can create domain user accounts?
  4. Who can create Organizational Units?
Here's why -

Anyone who can create security groups can potentially launch such an attack very quickly using the power of automation. Now, although the ability to create a large number of security groups can be prevented by using Quotas, the quota limit restriction can be partly circumvented if the attacker can create new user accounts, and use those accounts to create additional security groups.

This is why it is equally important to know who can create user accounts, where and how.

Finally, even if you know who can create user accounts, you should also know who can create Organizational Units (and strictly speaking who can modify permissions on existing OUs as well) because if you can create OUs, or modify permissions on OUs, you could grant any domain account of your choice, the ability to create accounts and groups.

One other thing - along the same lines, if someone can modify the membership of a large number of security groups, he could also launch this attack, and quotas would not prevent him from doing so, since quotas only impact object creations.

This is why it is very important to know exactly who is currently delegated the ability to perform these tasks in your Active Directory environment -

Who can create security groups in Active Directory?

Oh, and this point can never be over-emphasized - "Finding out who has what permissions in Active Directory IS NOT THE SAME as finding out who can perform these tasks." In fact, if you merely rely on the former, you're in dangerous territory because you're operating on inaccurate information.

In order to correctly find out who is delegated these tasks in your environment, you have to first determine true effective permissions on virtually all objects in your Active Directory, and based on that determine who is truly delegated the ability to perform these tasks.

In fact, the mission-critical subject of how to correctly determine true effective permissions in Active Directory will be the subject of my next blog entry. Until then, if you want some more info on it, you can find it here.

Alright, my time's up.

Best wishes,

PS: I generally prefer to let my work speak for itself, but sometimes it is important to address vital issues. Also, in case you liked this, you may also like this and my take on the OPM Data Breach

PS2: If you found this useful, you're welcome to share it. I only ask that since this is copyrighted material, if you do quote any of it, please do acknowledge the source with a link. Thank you.

No comments:

Post a Comment