Sessions


Before you can assess application security in a Windows environment, you must understand the system's security features. You need to know how security is applied and how access to system resources is mediated. Having this knowledge enables you to identify what users can and can't access and how the OS decides what privileges users have. Therefore, this section introduces Windows sessions and the elements of access control that are referred to throughout this chapter and Chapter 12.

Windows is a multiuser operating systemmeaning it can deal with multiple logged-on users simultaneously. Handling multiple simultaneous logons is accomplished by establishing sessions for each user who logs on successfully. A session is simply a mechanism for encapsulating data relevant to a logon instance. The data a session object maintains includes the following:

  • Information for governing process access rights

  • Data accessible to constituent processes in a session

  • Selected behavioral characteristics for processes started in a session

Sessions ensure that concurrently logged-on users can run applications more or less isolated from each other, thus preventing users from interfering with each other's processes to a certain extent. Session data structures and sessionwide accessible objects are explained later in this section.

Note

Keith Brown is the author of The .NET Developer's Guide to Windows Security (Addison-Wesley, 2005), which is an exceptional reference for the Windows security model. If you're more concerned with the lower-level API, you might want to consider his earlier book Programming Windows Security (Addison-Wesley, 2000). However the coverage centers on Windows NT and 2000, so some of the material is no longer current.


Security IDs

Windows access control mechanisms determine what access an entity has to a resource. An entity's identity is determined by the security ID (SID), a structure that contains a number of fields, including a revision level, an identifier authority value, a variable-length subauthority, and a relative ID (RID). SIDs are often represented in a text format, with each subfield broken out separately, like so:

S-<revision>-<identifier authority>-<subauthority>-<RID>


An example of a SID might look something like this:

S-1-5-32-545


This SID identifies the well-known Users group. The 1 is the revision number, which has been the same for every version of Windows; the 5 is the authority ID of SECURITY_NT_AUTHORITY; the 32 is the subauthority for built-in accounts; and the 545 identifies the Users group.

Note

SIDs can be converted between text and structure form by using the ConvertStringSidToSid() and ConvertSidToStringSid() functions, respectively.


For the purposes of this discussion, you can just think of a SID as a unique number that identifies an entity on the system, more commonly referred to as a "principal." A principal is any uniquely identifiable entity on the system that can be granted specific access to a system resource. Principals can be users, service accounts, groups, or machinesany entity associated with a logon session or a collection of these entities.

You frequently encounter SIDs throughout the discussion of the Windows security model, because they play an essential role in determining who has access to what. The important thing to remember about SIDs is that account names can change over time and vary between languages, but a SID, after it's assigned, never changes. Further, the values of well-known SIDsaccounts guaranteed to exist on every system or domainnever change, either. Here are some examples of wellknown SIDs:

Administrator: S-1-5-<domain ID>-500

Administrators group: S-1-5-32-544

Everyone group: S-1-1-0

Local system account: S-1-5-18

Local service account: S-1-5-19

Local network account: S-1-5-20

Logon Rights

Windows logon rights aren't a session component but should be understood in the context of sessions. Logon rights determine whether a user can establish a logon session on a machine and what type of session is allowed. To view these rights, open the Local Security Policy Editor and navigate to Local Policies and then User Rights Assignment. Table 11-1 briefly summarizes these rights from the MSDN listing.

Table 11-1. Logon Rights

Right

Description

SeNetworkLogonRight

Allows a user to connect to the computer from the network.

SeRemoteInteractiveLogonRight

Allows a user to log on to the computer via a Remote Desktop connection.

SeBatchLogonRight

Allows a user to log on using a batch-queue facility, such as the Task Scheduler service.

SeInteractiveLogonRight

Allows a user to log on locally and start an interactive session on the computer.

Note: Users who don't have this right can start a remote interactive session on the computer if they have the SeRemoteInteractive right.

SeServiceLogonRight

Allows a security principal to log on as a service. Services can be configured to run under the Local System, Local Service, or Network Service accounts, which have a built-in right to log on as a service. Any service that runs under a separate user account must be assigned this right.

SeDenyNetworkLogonRight

Prohibits a user from connecting to the computer from the network.

SeDenyInteractiveLogonRight

Prohibits a user from logging on directly at the keyboard.

SeDenyBatchLogonRight

Prohibits a user from logging on using a batch-queue facility.

SeDenyServiceLogonRight

Prohibits a user from logging on as a service.

SeDenyRemoteInteractiveLogonRight

Prohibits a user from logging on to the computer via a Remote Desktop connection.


Access Tokens

Access tokens are system objects that describe the security context for a process or thread. They are used to determine whether a process can or can't access a securable object or perform a system task that requires special privilege. Access tokens can be derived from a number of sources, but they are initially created when a user starts a new session. This initial token is referred to as a primary access token; it's assigned to all new processes started in the current logon session. The MSDN description for access tokens contains a list of components that make up the access token; the following list shows the main fields of interest:

  • Security Identifier (SID) This SID identifies the user associated with this access token.

  • Group List This series of SIDs identifies all the groups the user belongs to at the time of logon.

  • Session Security Identifier This field is the logon session identifier associated with this token. Many tokens are associated with a single session.

  • Privilege List This field is a list of special privileges, or rights, required to perform system-related tasks.

  • Default DACL Every securable object creation routine takes a security descriptor parameter. The default DACL is applied when a NULL DACL is supplied and inheritance rules require a DACL.

  • Restricting SID List This field is a list of restricted SIDs for the token. Restricted tokens are discussed in more detail in "Restricted Tokens" later in this chapter.

A token containing all this information is created at every user logon and is later copied for each process and thread spawned in the session. Note that the token is copied, as opposed to a reference being passed, because each process or thread can optionally modify certain attributes of its access token. By using a copy for each process and thread, modifications don't affect other processes in the same session.

Only certain parts of the access token can be modified by a process and a thread. Obviously, the unrestricted capability to change certain components of the token (such as the user and group SIDs or the privileges list) would completely undermine the security model. However, several other fields (such as the default DACL) can be modified safely to address access control concerns in a session.

Privileges

As noted earlier, privileges are special permissions that allow a principal to perform system-related tasks. Table 11-2 lists privileges that can be granted to a principal.

Table 11-2. Windows Privileges

Privilege Name

Description

SeAssignPrimaryTokenPrivilege

Allows a user to assign the primary access token for a process or thread.

SeAuditPrivilege

Allows a user to generate security logs.

SeBackupPrivilege

Allows a user to create backups of system files and directories.

SeChangeNotifyPrivilege

Allows a user to be notified when certain files or folders are changed.

SeCreateGlobalPrivilege

Allows a user to create global objects (available only in Windows Server 2003, Windows XP SP2, Windows 2000 SP4, and later).

SeCreatePagefilePrivilege

Allows a user to create a page file.

SeCreatePermanentPrivilege

Allows a user to create a permanent system object.

SeCreateTokenPrivilege

Allows a user to create new token objects.

SeDebugPrivilege

Allows a user to attach to and debug processes.

SeEnableDelegationPrivilege

Enables computer and user accounts to be trusted for delegation.

SeImpersonateName

Allows a user to impersonate a client (available only in Windows Server 2003, Windows XP SP2, Windows 2000 SP4, and later).

SeIncreaseBasePriorityPrivilege

Allows a user to increase the scheduling priority of a process.

SeIncreaseQuotaPrivilege

Allows a user to increase his or her quota.

SeLoadDriverPrivilege

Allows a user to load kernel drivers.

SeLockMemoryPrivilege

Allows a user to lock pages in memory.

SeMachineAccountPrivilege

Allows a user to add a workstation to the domain.

SeManageVolumePrivilege

Allows a user to manage files on a volume.

SeProfileSingleProcessPrivilege

Allows a user to profile a single process.

SeRemoteShutdownPrivilege

Allows a user to shut down the machine remotely.

SeRestorePrivilege

Allows a user to restore system files and directories.

SeSecurityPrivilege

Allows a user to manage audit logs.

SeShutdownPrivilege

Allows a user to shut down the machine.

SeSyncAgentPrivilege

Allows the use of synchronization services.

SeSystemEnvironmentPrivilege

Allows modification of firmware environment variables.

SeSystemProfilePrivilege

Allows a user to profile system performance.

SeSystemtimePrivilege

Allows a user to change the system time.

SeTakeOwnershipPrivilege

Allows a user to take ownership of objects and files owned by other users.

SeTcbPrivilege

Identifies a user as part of the trusted computing base.

SeUnlockPrivilege

Allows a user to unlock a laptop.

SeUnsolicitedInputPrivilege

Allows a user to read input from a terminal device.


Privileges play a vital role in system integrity; obviously, the haphazard assignment of privileges could result in a compromise of the system. For example, a user with SeDebugPrivilege can take over processes owned by other users; this privilege would allow attackers to run arbitrary code in the context of another account. Similarly, a user with SeLoadDriverPrivilege might load a malicious driver into kernel mode, thus taking complete control of the system.

The default allocation of privileges is generally safe. However, services and similar applications might require additional access. If this access isn't carefully considered, it could create operational vulnerabilities that allow privilege escalation. Some applications must also downgrade permissions dynamically, and failing to do so might result in similar implementation vulnerabilities. This concern is addressed more later in the "Restricted Tokens" section.

Group List

An access token contains a list of SIDs for all the associated user's group memberships. When attempting to access an object, the object DACL is checked against entries in the group list. Access is refused if no matching entries exist or if an entry explicitly denies access. Otherwise, access is granted if a matching SID entry provides the requested level of access or higher.

The SID list is generated at logon and can't be updated during a session. This approach allows performing access checks quickly and efficiently, even in a distributed environment. To see how this works, you can easily alter your account membership with the Microsoft Management Console. Any changes you make affect the account, but the current session is untouched. You have to log back on under a new session for changes in group membership to take effect.

There's an exception to the requirement that group membership can't be altered for an active session. Group memberships can be somewhat altered through the use of SID attributes, which are parameters associated with each SID entry in the group list. They define how the SID entry applies and how it can be altered. So although new groups can't be added, existing groups can be altered by manipulating their attributes, and although groups can't be removed, any SID entry that isn't mandatory can be disabled. Table 11-3 describes attributes that can be associated with SIDs in a group list.

Table 11-3. SID Attributes

SID Attribute

Meaning

SE_GROUP_ENABLED

This SID is enabled for access checks.

SE_GROUP_ENABLED_BY_DEFAULT

By default, this SID is enabled. This information is used when a token is being reverted to its default state.

SE_GROUP_LOGON_ID

This SID is a logon session SID.

SE_GROUP_MANDATORY

This group SID is enabled and can't be disabled.

SID_GROUP_OWNER

The SID describes the owner of a group or object.

SE_GROUP_RESOURCE

This group SID identifies a domain local group.

SE_GROUP_USE_FOR_DENY_ONLY

This SID can be used for deny access control entries (ACEs) only; it's ignored when examining allow ACEs for an object.


Restricted TokensF

Some entries in a group list can be disabled, but even more extreme measures can be taken to reduce the permissions granted to a token. To do this, you create a restricted token, which is a token that has a nonempty restricted SID list. An access check for a restricted token differs from a normal token. An access check succeeds only if the DACL SID entry is present in both the normal group list and the restricted group list. Further, restricted tokens can set the SE_GROUP_USE_FOR_DENY_ONLY flag on mandatory SID entries. This approach can even be used to prevent the account from using its own SID for granting access to a resource.

A restricted token can also revoke any privileges currently assigned to the token. By combining group and privilege restrictions, drastically limiting the access granted to a token object is possible. A restricted token is created by using the CreateRestrictedToken() function; its prototype is shown as follows:

BOOL CreateRestrictedToken(HANDLE ExistingTokenHandle,         DWORD Flags,         DWORD DisableSidCount,         PSID_AND_ATTRIBUTES SidsToDisable,         DWORD DeletePrivilegeCount,         PLUID_AND_ATTRIBUTES PrivilegesToDelete,         DWORD RestrictedSidCount,         PSID_AND_ATTRIBUTES SidsToRestrict,         HANDLE NewTokenHandle)


This function is used to supply a list of SIDs that can be disabled, to delete privileges from a token, and to add restricted SIDs to an access token. This effectively means that any process can create an access token containing a subset of the privileges and resource access rights the original token had.

Of course, creating a new token might not be appropriate in many circumstances. Instead, you can modify attributes of the existing token with these functions: AdjustTokenGroups() and AdjustTokenPrivileges(). These functions can be used to alter an existing token by modifying group membership, as described in the section on group lists, or by altering token privileges. Here's the prototype of AdjustTokenGroups():

BOOL AdjustTokenGroups(HANDLE TokenHandle,         BOOL ResetToDefault,         PTOKEN_GROUPS NewState,         DWORD BufferLength,         PTOKEN_GROUPS PreviousState,         PDWORD ReturnLength)


This function can enable and disable groups in an access token, but the specified groups must already exist in the token's list of group SIDs. This function simply sets or clears the attributes discussed in the previous section. Primarily, it's used to set or clear the SE_GROUP_ENABLED attribute, which determines how the group affects an access check. A value of TRUE for the ResetToDefault parameter causes the NewState value to be ignored and the default state of the access token restored.

Similarly, a process can enable or disable the privileges in an access token by using the AdjustTokenPrivileges() function. Here's the function prototype:

BOOL AdjustTokenPrivileges(HANDLE TokenHandle,         BOOL DisableAllPrivileges,         PTOKEN_PRIVILEGES NewState,         DWORD BufferLength,         PTOKEN_PRIVILEGES PreviousState,         PDWORD ReturnLength)


Modifications made with AdjustTokenGroups() aren't irrevocable. Further, modifications made by using AdjustTokenPrivileges() are permanent only in Windows XP SP2 and Server 2003 or later and only if the SE_PRIVILEGE_REMOVED flag is set in the NewState parameter. This creates situations in which attackers can reset the token to its default state should they gain control of the process through a vulnerability. A restricted token, however, prevents the token from being reset to its original group list and privilege state.

Software Restriction Policies (SAFER) API

Windows XP and Server 2003 added the Software Restriction Policies (SAFER) API to provide a simpler method of running processes under additional restrictions. The SaferCreateLevel() function provides machine and user scope restrictions and accepts five levels of security, ranging from disallowed to fully trusted. It can be used with SaferCreateTokenFromLevel() to create restricted tokens more easily. The SAFER levels from the MSDN are listed in Table 11-4.

Table 11-4. SAFER Levels

Value

Meaning

SAFER_LEVELID_DISALLOWED

Software doesn't run, regardless of the user's access rights.

SAFER_LEVELID_UNTRUSTED

Allows programs to run with access only to resources granted to well-known groups, blocking access to Administrator and Power User privileges and personally granted rights.

SAFER_LEVELID_CONSTRAINED

Software can't access certain resources, such as cryptographic keys and credentials, regardless of the user's access rights.

SAFER_LEVELID_NORMALUSER

Allows programs to run as a user who doesn't have Administrator or Power User access rights. Software can access resources accessible by normal users.

SAFER_LEVELID_FULLYTRUSTED

Software access rights are determined by the user's access rights.


Running Under Different Contexts

Windows provides the capability to change the current thread's token or create a new process under a different token. Functionally, this capability is similar to the su command in UNIX. However, the implementation and use of the Windows functionality is very different. The first major difference is that Windows requires the user's password credentials to create a token for another user context.

Note

At first, requiring the user's password credentials to create a token for another user context might seem a bit odd. The local system account has unrestricted access to the account database and at some level eventually creates the logon session and token. Of course, this is true for a stand-alone system, and undocumented API calls could be used to manually generate a logon session and token for any user. However, Windows stand-alone authentication is more of a subset of Windows domain authentication. In a domain environment, only a domain controller has the context necessary to issue credentials for domain-level users. So a local system could use the native API calls to forge a domain token, but it would lack credentials needed for any network authentication. In the end, it seems the Windows designers chose to punt on this issue. They simply provide an API that always requires password credentials for authenticating a user.


There are actually a few options for creating a process under a new user context. The first option works in Windows 2000 and later and is available to any authenticated user. It involves starting a process under a new user session by calling CreateProcessWithLogonW(). This function provides a programmatic interface to the Secondary Logon Service and is basically the same as shelling the RunAs command.

The next option for creating a new user context uses the lower-level Win32 security function, LogonUser(). In Windows 2000 and earlier, this function requires the caller to have the SE_TCB_NAME privilege (described as the "act as part of the operating system" right); this right should be granted only to highly privileged accounts. This restriction severely limits the use of this function on earlier versions of Windows; it's useful only for providing external authentication in services that don't use native Windows IPC mechanisms.

Windows provides seven different logon types, depending on how the token must be used. This distinction is important because it can improve performance and prevent an exposure of credentials. Table 11-5 lists the available logon types from the MSDN.

Table 11-5. Logon Types

Value

Meaning

LOGON32_LOGON_BATCH

This logon type is intended for batch servers, where processes can be running on behalf of users without their direct intervention. This type is also for higher-performance servers that process many plain-text authentication attempts at a time, such as mail or Web servers. The LogonUser() function doesn't cache credentials for this logon type.

LOGON32_LOGON_INTERACTIVE

This logon type is intended for users who are interactively using the computer, such as a user being logged on by a terminal server, remote shell, or similar process. This logon type has the additional expense of caching logon information for disconnected operations; therefore, it's inappropriate for some client/server applications, such as a mail server.

LOGON32_LOGON_NETWORK

This logon type is intended for high-performance servers to authenticate plain-text passwords. The LogonUser() function doesn't cache credentials for this logon type.

LOGON32_LOGON_NETWORK_CLEARTEXT

This logon type preserves the name and password in the authentication package, which allows the server to make connections to other network servers while impersonating the client. A server can accept plain-text credentials from a client, call LogonUser(), verify that the user can access the system across the network, and still communicate with other servers. Windows NT: This value is not supported.

LOGON32_LOGON_NEW_CREDENTIALS

This logon type allows the caller to clone its current token and specify new credentials for outbound connections. The new logon session has the same local identifier but uses different credentials for other network connections. This logon type is supported only by the LOGON32_PROVIDER_WINNT50 logon provider. Windows NT: This value is not supported.

LOGON32_LOGON_SERVICE

Indicates a service-type logon. The account provided must have the service privilege enabled.

LOGON32_LOGON_UNLOCK

This logon type is for graphical identification and authentication (GINA) dynamic link libraries (DLLs) that log on users who are interactively using the computer. This logon type can generate a unique audit record that shows when the workstation was unlocked.


As you can see, each logon type performs slightly differently in handling credentials. For example, developers should use the LOGON32_LOGON_NETWORK type for a service that requires only authentication on the local system. Using another authentication mechanism in this situation, such as LOGON32_INTERACTIVE or LOGON32_NETWORK_PLAINTEXT, might cache sensitive user credentials unnecessarily. Attackers might then be able to steal credentials via an impersonation or Server Message Block (SMB) relay exploit. (Impersonation attacks are explained in more detail in Chapter 12.)

After a token has been generated, it can be used to spawn another process by using CreateProcessAsUser() or CreateProcessWithTokenW(). Most user applications create a new token only when spawning a new process. However, a service might choose to replace credentials for the current thread by using SetThreadToken(), which brings you to a unique Windows capability known as impersonation.

Impersonation

Impersonation is the capability for a thread running under one user session to use the credentials of another user session. It's done in two ways. The first method is to generate a token as described previously and assign that token to a thread with SetThreadToken(). This function requires that the caller have the SE_TOKEN_IMPERSONATE right on the target thread handle. The second, and more complex, form of impersonation is used in IPC in a client/server scenario. It's intended to allow the server process to duplicate (or impersonate) the client's credentials. This capability allows Windows systems to perform a single sign-on (SSO) on an individual system or across a domain environment. This capability is discussed in more detail in Chapter 12.




The Art of Software Security Assessment. Identifying and Preventing Software Vulnerabilities
The Art of Software Security Assessment: Identifying and Preventing Software Vulnerabilities
ISBN: 0321444426
EAN: 2147483647
Year: 2004
Pages: 194

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