What’s in a Token (Part 2): Impersonation
It’s Randy again. In my last blog post, we discussed that the token is the identification for a process. The token object contains a list of security identifiers, rights and privileges that the Windows Security Subsystem uses to grant access to secured resources and tasks. Each process running on a computer will contain a token to represent who is doing the work for this activity. With identification on each process, Windows can guard against unauthorized access to sensitive data as well as protecting the integrity of the operating system. At any given time, there are different processes running on a computer to represent the different activities required to function and to do what we ask. Some of these processes run as the logged on user (interactive logon), while other processes run under a service startup account or as the computer itself.
Sometimes a process will need to perform one task as someone and another task as someone else to successfully carry out its activity. Each of these tasks in a process are defined as threads. By default a thread uses the token of the process running the thread; this is called its Primary Token. If a process needs to perform a task as if it were someone else, a thread can use an Impersonation Token to identify itself as the other person instead as the identity of the process.
As we discuss impersonation, think of this real world analogy: Consider purchasing groceries with your credit card at the checkout counter of a grocery store. You give your credit card to the cashier, and the cashier takes your card and swipes it through the cash register and processes the transaction as if they were you. If we could not impersonate, then everyone in the checkout line would have to get behind the cash register and initiate this transaction themselves and I don’t think management would like giving the general public access to their cash registers. Now one person with the job qualification to charge credit cards can perform this action on every customer’s behalf and maintaining their identity with the help of the credit card. A good example of impersonation would be connecting to a network share on a file server from your workstation. On the file server, we have the Server service responsible for handling the network (SMB) request from the client. The Server service is running under “Local System” (SID: S-1-5-18) and is responsible for filling the request made by the workstation. The workstation process that wants to access the share is running as the logged on user to the workstation. In order for the operating system to control access to the file on the file server, the Server service must use the requestor’s credentials when retrieving the file and not that of the Local System. The Server service process, running as Local System, creates a thread with an Impersonation Token to perform the task of accessing the file with the identity of the user logged onto the workstation. It is difficult to catch this behavior, because as soon as the impersonating thread completes its task, the token will revert back to the Primary token (the token of the process that creates the thread.) We’ll go through this scenario and find evidence of impersonation.
A great tool to witness Impersonation is Process Monitor. This tool logs all access to files and registry at the time of access, therefore we see a snapshot of the impersonating thread before it reverts back to the primary token. It will output a lot of entries, so you will want to use the filter option to locate the path to the file you are monitoring. We will monitor access to test.txt on the tools share. On the file server, we will open test.txt using the local path (C:\Tools.) versus the UNC path of the share \\WtipFS1\Tools) Here are two screenshots below.
This is some of the output from accessing test.txt using the local path. Notice that Explorer.exe is the process that opens this file. As mentioned in my first blog post, explorer.exe is the user shell that is running with the token of the logged on user. This token is used to compare against the security descriptor on test.txt, allowing us to set permissions to grant or deny access based on the user credentials.
This is some of the output from accessing test.txt using the UNC path. It makes no difference that we use a UNC path from the file server or from a workstation; both scenarios will use the Redirector and Server service to get the file. When accessing via the UNC path, we see the System services do all the work. The process is using the token of the local system which will have access to all the files regardless of what user is requesting the file. In order to enforce the security on the file, the local system needs to impersonate the user and present the requesting user’s token to the security subsystem to compare against the security descriptor on test.txt. Below we see the properties of the log event in process monitor (double click on one of the log entry lines) when the local system opens our test.txt file.
Notice at the bottom that the local system is impersonating Billy. This way, we could deny Billy access to this file and our permissions will be adhered even when another process tries to get this file on Billy’s behalf.
In our example above, we see that the local system impersonates users in order to provide services. This behavior is not limited to the local system. We can grant this ability to anybody by using the security privileges mentioned in my previous blog post. The privilege needed is Impersonate a client after authentication (SeImpersonatePrivilege.) This privilege is listed in the token of the process and is checked by the security subsystem when that process wants to open a thread with an impersonation token.
Auditing is another good tool to track some of the symptoms of impersonation. As mentioned above, we require the “ impersonate a client after authentication privilege” for a process to use an impersonation token on a worker thread. If we audit privilege use, then we will see this privilege enumerated when a process starts. In our File server example, the System process actually has a privilege of Act as part of the operating system (SeTcbPrivilege) which changes all the rules by giving the process complete authority to the local system. Referred to by developers as TCB (trusted computer base), this permits the process to call LSALogonUser and authenticate as anyone and access anything local to the system. This is why careful consideration needs to be made when granting this privilege.
Another interesting application to experiment with impersonation is Internet Information Server. It is easy to configure different accounts for the application pool that runs a website. It is also easy to configure anonymous access or Windows Integrated and witness the different behaviors of each. By default, our website is running under the credentials of the local IWAN account. When we restart the IIS services, we see an audit event, like the one below, of the IWAN account enumerating its privilege use.
We can also enable network logon auditing on the file server. When we access the default website from a different computer, then we see a logon event, on the file server hosting the website, similar to the one below.
In this audit event we see that Billy accessed the website on the fileserver. Notice that the logon type is set to 3, which equates to a Network Logon. A network logon tells us that a remote process is requesting a resource on this box and providing credentials. A local service must handle this request, therefore impersonating the credentials of the remote process. If LogonType is Interactive or Batch, a primary token is generated to represent the new user. If LogonType is Network, an impersonation token is generated. To learn more about the logon process, you can research LsaLogonUser or the Logon and Authentication technical reference.
Now we have given a process the ability to perform a task as a different user; sounds like a pretty powerful privilege - but also a potential area for exploitation. This is why we control impersonation by providing different levels of impersonation; Anonymous, Identification, Impersonation, and Delegation. These levels refer to what you can do with the impersonation token after you get it. Anonymous is just like it sounds – we can impersonate you as an anonymous user and that’s all. Identification is when a process can pull your token to validate credentials, but cannot do anything with the token. Impersonation means that the process can perform task as a different user; as in our network share or IIS example above. Impersonation is limited only to tasks local to that computer, a process cannot “run a task” or “request an object” that resides outside of the system because we grant the privilege on a session by session basis (different computer, different session.) Delegation is one step beyond Impersonation, where the process can call resources and perform tasks on other computers than it. The fact we can impersonate beyond the boundaries of the local system is an important distinction between impersonation and delegation; the target resource off the system will have no knowledge of the middle-tier impersonator. We will not go into great detail about Delegation, but this is a feature provided to us by the Kerberos authentication protocol and also referred to “double hop” authentication – meaning that our credentials hop from one computer to the next, rather than us having to go to each computer individually.
We define the level of impersonation in two places. The first place is in the client/server code itself. Here the client tells the server process what exactly he can do with these credentials when he gets them during the InitializeSecurityContext function. This is one way to safeguard granting more power than necessary, but we are reliant on the software developers for this safety-net. The second place is in granting the needed rights and privileges to the server process, which is controlled by us network administrators. We already discussed the SeImpersonatePrivilege, but there are additional options with delegation set on the client object guarding it as non-delegable and on the server process by permitting delegation and even constraining delegation to limit the tasks and remote computers to which it can perform.
This summarizes the concept of the impersonation token. In a future blog post, I will be discussing how the process impersonates itself with certain privileges and security groups removed, referred to as a restricted token. The benefits of this is to not cookie-cut a set of credentials to all or nothing, why give a process more rights than it needs to do its job. This has been enhanced in Vista with user account control and split tokens to logon a user with two separate tokens (a full and a restricted) and require user acknowledgement to initiate a process that requires the full token.
- Randy Turner