Understanding User Context

[Previous] [Next]

The system maintains user context information in a token (introduced in Chapter 10). Before I discuss how the system uses the token to maintain a sense of user identity, I will discuss how the system builds a token.

Authentication and Token Contents

When you interactively log on to a workstation or server machine running Microsoft Windows 2000, you typically enter a username and a password. The username is a trustee account that exists either in Active Directory located on a domain controller or as a local user account maintained in a security database on the local machine. The password is the user account's credentials, which the system uses to authenticate the logon.

After the user logs on, the system begins to gather information about the user account (unless of course the username or password is incorrect, in which case the logon fails). If the user account is a domain account, the system gathers domain-level information such as the domain groups of which the user is a member. Regardless of whether the account is a domain account, the system begins gathering information about the user relative to the local machine, such as the local group accounts of which the user is a member (including nested memberships via domain groups that are members of local groups). The system creates a list of privileges that are assigned to the user account as well as all the users' group accounts. All this information is compiled into a data structure that is maintained in a system kernel object, which is the token.

After the system has authenticated a logon attempt, the token is the user's identity as far as Windows security is concerned. This identity consists of the security identifier (SID) for the user trustee account and all the information shown in Table 11-1. (See Chapter 9 for information on SIDs and trustee accounts.)

As you can see, a wealth of information is maintained in a token. Think of the token as a very detailed "virtual security badge," where the token's user SID is the name printed on the badge and the group SIDs are the membership information printed on the badge. The privileges in the token indicate certain system-wide rights; the remaining data is mainly informational. The system references this virtual badge every time you attempt to access a secure component in the system.

Tokens and Executing Code

So far, I have covered how a token is built (in general terms) and what information is stored in it. Now I need to clarify how the information in a token is used to assure that code is executed securely.

Every process in Windows 2000 owns a single token, and as you know, this token is the user context for the process. When a process calls CreateProcess, the system makes a duplicate of the calling process's token and associates the new token with the new process. In this way, your user context propagates throughout the system, from the moment that you log on to the moment that the last process owning one of your tokens terminates. Every time you log on, the system builds a token for your user context and then launches Microsoft Windows Explorer and associates the token with Explorer's process. Each time you launch a program from Explorer, the new process inherits a copy of the original token. You are not logged off the system until each process has terminated and the Explorer process has exited, closing the last handle to the last token object for your user context.

Table 11-1. Contents of a token

Token Information Description
Token user SID A SID representing the user account for which the token was created. This account is commonly referred to as the token user.
Token group SIDs SIDs for the groups of which the token user is a member. This includes built-in accounts such as Everyone and Authenticated Users.
Logon SID A unique SID created at the time of authentication. This SID uniquely identifies a logon session from other logon sessions, even if the other sessions are for the same token user. I will discuss the logon SID in more detail later in this chapter.
Privileges A list of privileges held by the token user and group trustee accounts. Privileges are discussed in detail in Chapter 9, as well as later in this chapter.
Default owner SID A SID indicating the owner of objects created with default security by code running under this token. Default security is discussed in Chapter 10 and later in this chapter.
Default group SID A SID indicating the primary group of objects created with default security by code running under this token. Default security is discussed later in this chapter and in Chapter 10.
Default DACL A SID indicating the discretionary access control list (DACL) of objects created with default security by code running under this token. Default security is discussed in Chapter 10 and later in this chapter.
Token source An eight-character "source name" set by the system component that created the token.
Token type The type of token, which can be either primary or impersonation. Primary and impersonation tokens will be discussed in more detail later in this chapter.
Restricting SIDs Optional trustee accounts used to restrict access for code running under this token. Restricted SIDs are discussed in detail later in this chapter.
Impersonation level The impersonation level of a token indicates to what degree a server can act as the client. Impersonation levels are discussed later in this chapter.
Security descriptor The token is a secured object in Windows, and like all secured objects, it has a security descriptor, which controls access to the object.
Credential information Some tokens have credential information. These tokens can act on behalf of the token user on the network, as well as on the local machine. Credential information is discussed in more detail throughout this chapter.

When any thread in your process executes a system function, which requires knowledge of security, the system checks your process's token for the information. This means that each time you ask the system for a handle to a secured object such as a registry key or a mutex, the system performs an access check, looking up necessary information in your token. Also, each time you call a function such as GetUserName, or any other function that must identify the user context of the executing code, the system retrieves the information from the token.

Although you can retrieve the handle to a token object for a process, setting the token for a process is impossible. (Actually, the system has the power to set the token for a process, but this is not exposed to the developer via the API.) So a process's token, or identity, is the one that the process is stuck with until it dies. Windows does, however, provide a very cool feature that allows you to change the token under which your code is executing, called impersonation.

Overview of Impersonation

Impersonation is implemented by associating a token with a thread of execution in a process. When you do this, this thread (for the most part) takes on the identity associated with its impersonation token. This thread is said to be "impersonating" a user or a security context. All other threads in the process will continue to execute code on behalf of the process's token unless they are also impersonating another user context. When the thread no longer needs to behave as though it were another user, it can revert to its normal state, which causes the thread to become itself again and use the process's token. As you can imagine, impersonation is very convenient in a client/server environment, in which a server is performing tasks on behalf of a client with a different security context.

Before moving on, I should clarify my assertion that a thread (for the most part) takes on the identity associated with its impersonation token. Typically, when you call a function that requires token information, the system checks for a thread token, and if one is not found, the system defaults to the process's token. Since threads don't naturally have tokens, the process's token is the natural security context for the process. However, in some cases a system function will still use a process's token even when the calling thread is running under an impersonation token.

For example, if an impersonating thread calls CreateProcess to create a new process in the system, the new process inherits the handle associated with the calling process, not with the impersonation token associated with the calling thread. Additionally, any function that requires the SE_TCB_NAME privilege (of which we will be discussing at least one, LogonUser, later in this chapter) or the SE_AUDIT_NAME privilege uses the process's token rather than checking the thread for an impersonation token. We'll talk more about impersonation later in this chapter.

You now understand how the system builds a token for you when you log on. You know how the system executes code that runs under your token (or security context), and you know that a thread can use impersonation to temporarily take on another identity. However, up to this point we have discussed only tokens that were created as a result of a logon with a user account such as "JClark" or "v-JeffrR". Now you'll learn how code that isn't running under a user account gets its token.

The LocalSystem Account

If you read Chapter 3, you are aware that services can be configured to execute regardless of whether a user is interactively logged on to the system. Also remember that you can configure a service to run as a user account, which requires you to enter the account name and password for the trustee account. It is easy to imagine the system logging on this user behind the scenes and building a token to use when running the process that executes the service's code. However, you can also configure a service to run as the LocalSystem account, which does not require an account name or a password.

The LocalSystem account is a special account on a system running Windows 2000 that is set aside for services and other processes running as "part of the operating system." As a result, the token that any process in the LocalSystem account has assigned to it is very powerful indeed. Here are some qualities of the LocalSystem account:

  • The LocalSystem account has nearly every privilege in the system assigned to it.
  • The LocalSystem account is an implicit member of the built-in Administrators group, and as such has all the access that an administrator has.
  • If the LocalSystem account does not have access to an object explicitly granted to it, it can always take ownership of the object and modify its DACL as desired.
  • The LocalSystem account has the SE_TCB_NAME or "Act as part of the operating system" privilege, so it can log on a user (to obtain a token), and execute code on behalf of that user, at will.
  • The LocalSystem account has direct or indirect access to everything on the local machine.

NOTE
In Microsoft Windows NT the LocalSystem account lived a life of irony—it had limitless access to its local machine and almost no access to securable objects on other machines on the network. The reason was that the LocalSystem account for one machine had no identity on another machine (in the same way that the Administrator account for one machine has no meaning on another machine). So objects on other machines were naturally secured against the LocalSystem account. Like Aladdin's genie, the LocalSystem account had "phenomenal cosmic powers! Itty bitty living space."

This limitation has been lifted, however, in network environments where the domain controller is a server running Windows 2000 using Active Directory. LocalSystem accounts now have trustee account status in Active Directory, and therefore can be given rights to securable objects on other machines in the domain.

The LocalSystem "genie" is now free from the single machine that used to be its prison. This change adds greatly to the flexibility of the LocalSystem account, but also opens potential security risks that must be closely administered.

Notice that a number of the functions provided for manipulation of tokens and other user context_related activities require privileges commonly granted only to the LocalSystem account. This is not a real problem, since your service will most likely run in the LocalSystem account. However, this need for privileges can be a bother when you are testing code and trying functions such as LogonUser and CreateProcessAsUser (both of which are discussed later in this chapter). We will discuss ways of dealing with the privilege issue and other problems arising from coding for the LocalSystem account later in this chapter.

User Context and Access Control

Although the previous chapter was entirely devoted to access control, I spent very little time focusing on the importance of user context. However, the security context that your process's (or thread's) token represents is absolutely critical to the function of access control.

Each time the system performs an access check, it scans the object's DACL for access control entries (ACEs) that match the user SID and group SIDs found in your token. If you are not explicitly allowed to read or modify an object's security, but you request permission to do so, the system compares the object's owner SID with the SIDs in your token, looking for a match. If one is found, you are granted access because you are an owner of the object.

As you can see, access control is completely reliant on the token. In fact, we will be discussing ways that you can exploit the token to have dramatic effects on access control in your software and in your system. Gaining an in-depth understanding of how these components work together to implement security under Windows 2000 will make you a powerful security developer indeed.



Programming Server-Side Applications for Microsoft Windows 2000
Programming Server-Side Applications for Microsoft Windows 2000 (Microsoft Programming)
ISBN: 0735607532
EAN: 2147483647
Year: 2000
Pages: 126

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net