Windows Integrity Mechanism Design

The Windows integrity mechanism is an extension of the Windows security architecture, which is based on the Security Reference Monitor in the kernel. The security reference monitor enforces access control by comparing user and group SIDs in the security access token with granted access permissions in the ACL of an object’s security descriptor. The integrity mechanism adds an integrity level to the security access token and a mandatory label access control entry to the system ACL (SACL) in the security descriptor.

The major parts of the integrity mechanism are:

  • Predefined integrity levels and their representation.
  • Integrity policies that restrict access permissions.
  • Integrity level assigned to the security access token.
  • Mandatory label access control entry.
  • Mandatory labels assigned to objects.
  • Integrity restrictions within the AccessCheck and kernel-mode SeAccessCheck APIs.

Each of these parts is described in more detail below. The Windows integrity mechanism is always in effect, independent of other security policy options. The integrity level checks, like the access control checks, are not optional. There are no security policy options to disable integrity level checks. Although the integrity mechanism supports UAC, the integrity mechanism remains in effect when UAC is disabled by security Group Policy.

Integrity levels

Windows defines integrity levels by using a SID. Using a SID to represent an integrity level makes it very easy to integrate the integrity mechanism into existing security data structures without requiring code changes. Integrity level SIDs have the following form: S-1-16-xxxx. Table 1 shows the components of integrity level SIDs.

Table 1   Integrity level SID identifier authority values

Value Description

16

Represents the Mandatory Label Authority (SECURITY_MANDATORY_LABEL_AUTHORITY).

xxxx

Represents the relative identifier (RID) field that is the integrity level. The RID is a hexadecimal value that represents the integrity level.

There are four primary integrity levels in Windows Vista with four corresponding values. A lower value indicates a lower integrity level or a lower level of trustworthiness. These values are defined in the header file, winnt.h. Table 2 shows the defined integrity levels and their corresponding values.

Table 2   Defined integrity levels and corresponding values

Value Description Symbol

0x0000

Untrusted level

SECURITY_MANDATORY_UNTRUSTED_RID

0x1000

Low integrity level

SECURITY_MANDATORY_LOW_RID

0x2000

Medium integrity level

SECURITY_MANDATORY_MEDIUM_RID

0x3000

High integrity level

SECURITY_MANDATORY_HIGH_RID

0x4000

System integrity level

SECURITY_MANDATORY_SYSTEM_RID

An example of a medium integrity level SID is this string: S-1-16-8192. The RID value of 8192 is the decimal equivalent of 0x2000.

The RIDs are separated by intervals of 0x1000 to allow for definition of additional levels in the future. The separation also allows assigning an integrity level to a process that is slightly higher than medium: for example, to meet specific system design goals.

The defined integrity level SIDs have string name values associated with them. Using the API LookupAccountSID will return string names for each integrity level SID. Table 3 shows the string names for the integrity levels.

Table 3   Integrity level string names

Integrity level SID Name

S-1-16-4096

Mandatory Label\Low Mandatory Level

S-1-16-8192

Mandatory Label\Medium Mandatory Level

S-1-16-12288

Mandatory Label\High Mandatory Level

S-1-16-16384

Mandatory Label\System Mandatory Level

The integrity levels are also defined as SID strings in the Security Descriptor Definition Language (SDDL). The SDDL defines the string format that the ConvertSecurityDescriptorToStringSecurityDescriptor and ConvertStringSecurityDescriptorToSecurityDescriptor functions use to describe a security descriptor as a text string. The language also defines string elements for describing information in the components of a security descriptor. Using the SDDL to define the integrity levels makes it convenient to define the integrity level of an object when the object is created. For more information about SID strings for integrity levels, see Windows Integrity Mechanism Resources. The SDDL support for mandatory labels is described in Appendix A: SDDL for Mandatory Labels.

Windows Vista uses integrity level SIDs in the security access token to represent the subject integrity level and uses integrity level SIDs in the mandatory label ACE in a security descriptor to represent the object integrity level.

Integrity policies

The Windows integrity mechanism uses simple policies to determine how to use the mandatory labels on objects to restrict the level of access that is available to lower-integrity subjects. This means that the policies limit the type of access that lower-integrity-level objects are allowed to have to higher-integrity-level objects. Table 4 shows the two policy categories.

Table 4   Integrity policy categories

Category Description

Access token mandatory policies

Set in the access token and determine how mandatory policies apply to the subject, which is represented in the access token.

Mandatory label policies

Set in the mandatory label ACE (described below) on objects, and determine how to restrict access to the object.

The integrity policies are used when the mandatory policy check is performed when evaluating access permissions on a securable object. The policies determine how access rights are restricted across integrity levels.

Mandatory access token policies

Table 5 shows the mandatory access token polices that are defined in Windows Vista.

Table 5   Mandatory access token policies in Windows Vista

Policy Description

TOKEN_MANDATORY_NO_WRITE_UP

The default policy that is assigned to all access tokens. The policy restricts write access by this subject to any object at a higher integrity level.

TOKEN_MANDATORY_NEW_PROCESS_MIN

Controls the behavior of assigning the integrity level to child processes. Normally, a child process inherits the integrity level of the parent process when the parent process access token is assigned to the child. With the NEW_PROCESS_MIN policy, the integrity level of the child process will be the minimum integrity level of either the parent access token, or the object integrity level of the executable file for the new process. This policy is set by default in all access tokens.

The NEW_PROCESS_MIN policy can be described by an example. Assume there is an executable program called lowcalc.exe. The program file is assigned a low integrity label. From a command prompt, the user runs lowcalc.exe. The parent process, cmd.exe, is running at a medium integrity level. Because the image file, lowcalc.exe, has a low integrity label, the NEW_PROCESS_MIN policy sets the integrity level of the new process, lowcalc, to low. This is illustrated in the example below in the section Designing Applications to Run at a Low Integrity Level.

Mandatory label policies

The mandatory label policies are defined as flags (bits) in the Mask field of the mandatory label access control entry. These policy flags determine the restrictions on access permissions that apply to lower integrity subjects. Table 6 shows the mandatory label policies that are defined in Windows Vista.

Table 6   Mandatory label policies in Windows Vista

Policy Description

SYSTEM_MANDATORY_POLICY_NO_WRITE_UP

The default policy on all object mandatory labels. The flag is equivalent to the NO_WRITE_UP access token policy. The policy restricts write access to the object by a subject with a lower integrity level.

SYSTEM_MANDATORY_POLICY_NO_READ_UP

Restricts read access to the object by a subject with a lower integrity level. The policy is used, for example, to restrict read access to the virtual memory address space of a process.

SYSTEM_MANDATORY_POLICY_NO_EXECUTE_UP

Restricts execute access to the object by a subject with a lower integrity level. The policy is used, for example, to restrict launch activation permissions on a COM class by lower integrity subjects.

These defined policies meet the design goals for Windows Vista. The architecture of the integrity mechanism allows for future expansion by defining additional policy options that control access permissions between subjects and objects at different integrity levels.

How integrity policies are mapped to generic rights

The mandatory policy check occurs as part of the AccessCheck security function. AccessCheck (and SeAccessCheck in kernel mode) has as one of the function parameters a GENERIC_MAPPING structure. The generic mapping provided by the caller maps object-specific access rights to the generic categories of read, write, and execute. The mandatory label policies implement restrictions on allowed access based on the generic categories. For a particular object type, the GENERIC_MAPPING communicates to the mandatory policy check which specific access rights are prohibited.

If the GENERIC_MAPPING structure that is passed into a call to AccessCheck is all zeros (0), the generic mapping is undefined. When the generic mapping is undefined, the mandatory policy check restricts all access rights by lower-integrity subjects. Resource managers that use AccessCheck for private object security and pass a GENERIC_MAPPING structure of all zeros will see Access Denied errors. A code change to the resource manager application is required to map object type-specific access rights to the generic access rights that the mandatory policy enforces.

How integrity levels are assigned to access tokens

The security access token is an internal data structure that the kernel uses. The security access token contains different information values that correspond to privileges, group membership, and other security-related details. Access token initialization occurs when a user interactively logs on to Windows, or when a network authentication occurs. When the access token is initialized, the user’s SID, group SIDs, and privileges are added, in addition to other values. Windows Vista assigns the integrity level for the access token when the access token is initialized.

The kernel assigns an access token to every process and thread. The primary access token of the process contains the integrity level associated with that process. In the Windows integrity mechanism, the integrity level of the process is referred to as the subject integrity level. If an application's access token contains the medium-integrity SID, then the application process is running at a medium-integrity level. Multiple application processes running under the same user account are assigned the same primary access token. That is how each of the applications is assigned the same integrity level.

Integrity levels are assigned to access tokens based on specific group SIDs being present in the TOKEN_GROUPS structure. The Windows kernel assigns an integrity level based on specific built-in user or group accounts. Windows Vista assigns an access token that has the Local System account SID present the integrity level of system, an access token with the local Administrators group SID present is assigned the integrity level of high, and an access token for a standard user account is assigned the integrity level of medium.

Table 7 shows the assignments of integrity level to the access token, based on the presence of specific SIDs.

Table 7   Integrity levels linked to specific SIDs

SID in access token Assigned integrity level

LocalSystem

System

LocalService

System

NetworkService

System

Administrators

High

Backup Operators

High

Network Configuration Operators

High

Cryptographic Operators

High

Authenticated Users

Medium

Everyone (World)

Low

Anonymous

Untrusted

Integrity levels define different levels of trustworthiness for applications running at different levels of access. Most applications in Windows Vista run at a standard user level of access at the medium integrity level. Applications at the medium integrity level do not experience any restrictions on how they interact with other applications and with data at the medium integrity level. Specific tasks or applications that require administrative rights run at a high integrity level. System services run at the system integrity level, because there are restrictions on their ability to interact with the default desktop, and they often run with powerful system privileges. A few applications that have been designed to run with the fewest rights possible, such as Protected Mode Internet Explorer, can run with a low integrity level.

Certain administrative Windows privileges can be assigned to an access token only with at least a high integrity level. If the access token integrity level is less than high, then specific administrative privileges are not allowed and are removed from the access token. The administrative privileges associated with a high integrity level are:

  • SE_CREATE_TOKEN_PRIVILEGE
  • SE_TCB_PRIVILEGE
  • SE_TAKE_OWNERSHIP_PRIVILEGE
  • SE_BACKUP_PRIVILEGE
  • SE_RESTORE_PRIVILEGE
  • SE_DEBUG_PRIVILEGE
  • SE_IMPERSONATE_PRIVILEGE
  • SE_RELABEL_PRIVILEGE
  • SE_LOAD_DRIVER_PRIVILEGE

Applications can assign a low integrity level to a duplicate access token when creating a child process. Windows might run an application process with a low integrity level if the executable program image file has a low mandatory label. These features are described later in this article.

How to get integrity level for an access token

The integrity level is stored in the access token using the TOKEN_GROUPS field. The TOKEN_GROUPS structure is a list of SIDs and attributes that identifies the group memberships for that user account. The access token integrity level is also identified in the group list using a SID attribute. The SID_AND_ATTRIBUTES structure contains the integrity level SID, and the integrity level is identified using the SE_GROUP_INTEGRITY and SE_GROUP_INTEGRITY_ENABLED attributes.

You can retrieve the access token integrity level from the access token by using the GetTokenInformation API. GetTokenInformation has a parameter to indicate what access token information class to retrieve. The TOKEN_INFORMATION_CLASS parameter has a defined value for the integrity level, TokenIntegrityLevel. The data structure returned is a TOKEN_MANDATORY_LABEL type.

To determine the integrity level of a process

  1. Open a handle to the access token of the process.

  2. Get the integrity level of the access token.

  3. Compare the integrity level SID to the system-defined integrity level RIDs.

Example code for getting the access token integrity level is shown in Appendix D.

How to view the integrity level for an access token

The integrity level in the security access token of a process can be viewed using tools that expose the security details of a process, such as Process Explorer from SysInternals.com. The following images show the display from Process Explorer with the Integrity Level column added to the view (to the right).

Figure 1   Integrity level in Process Explorer

If we look at the security properties of a specific process, such as explorer.exe, Process Explorer shows the integrity level in the list of groups that are defined in the security access token of the process. The following image shows the Mandatory Label/Medium Mandatory Level assigned to the access token for the process, explorer.exe.

Figure 2   Explorer.exe as a medium integrity level process

How to set the integrity level for an access token

Applications generally do not need to change the value of the integrity level of the process. Applications typically do not need to make changes to any of the values in the security access token. However, in some circumstances services that support local clients at different integrity levels might choose to carry out tasks at a lower integrity level. Impersonation is one way that a service thread may be running at a lower integrity level. When a service thread impersonates a local client, the impersonation thread has the client’s security context, which includes the client’s integrity level if the client is running on the same local machine.

Another way that an application can carry out an operation, such as creating a set of files and registry keys, at a lower integrity level is to set the TokenIntegrityLevel for the current thread access token. The new integrity level cannot be higher than the integrity level in the primary access token of the process.

To set the value of an access token integrity level on a thread

  1. Call OpenThreadToken to get a handle to the access token.

  2. Call GetTokenInformation with the TOKEN_INFORMATION_CLASS parameter value of TokenIntegrityLevel to save the current thread integrity level.

  3. Call SetTokenInformation with the TOKEN_INFORMATION_CLASS parameter value of TokenIntegrityLevel.

Because there is no security boundary within a process address space between threads at different integrity levels, application designers must consider the potential security risks of having code running in a thread at lower integrity running in a higher-integrity process. Most applications might find it simpler to create a separate process running at the lower integrity level to perform lower-integrity tasks.

An example of how to set the TokenIntegrityLevel and create a process at a lower integrity level is shown in How to set the integrity level for an access token.

Mandatory label ACE

The Windows integrity mechanism defines a new ACE type, the system mandatory label ACE. The mandatory label ACE is used to represent the mandatory label of an object in the object’s security descriptor. The mandatory label contains the integrity level and associated integrity policy. A mandatory label ACE is used only in the system ACL, or SACL, of the security descriptor. The SACL is a separate field in the security descriptor from the discretionary ACL (DACL).

Figure 3   Security descriptor fields

The discretionary ACL contains user and group access permissions to the object. Any user or group can make updates to the DACL with WRITE_DAC object access permissions. Discretionary ACLs can be updated more frequently and by different users. One of the design goals of the integrity mechanism is that the security system should maintain the label with an object after a mandatory label is applied to the object. Enforcing the appropriate mandatory label in the object security descriptor, with little or no impact to applications designed to manage ACLs, is accomplished by putting the mandatory label in the system ACL, where it is primarily under the control of the security system. The mandatory label is logically separate from the system audit entries in the SACL. There is no required order for the mandatory label to precede or follow the system audit entries in the SACL.

The mandatory label ACE is similar to an access allowed ACE, in that it contains an ACE header, an access mask, and a SID. The SID portion of the mandatory label ACE contains the integrity level SID. Table 8 shows the fields in the ACE header.

Table 8   Fields contained in the ACE header

ACE header field Value

AceType

SYSTEM_MANDATORY_LABEL_ACE_TYPE

AceFlags

Control flags that define inheritance of mandatory label ACE type

AceSize

Size of the mandatory label ACE

The mandatory label ACE contains a Mask field. The mask is used to define the mandatory policies that determine restrictions on the access permissions that apply to processes (or subjects) with a lower integrity level. An example policy used widely in Windows Vista is the NO_WRITE_UP policy. The NO_WRITE_UP policy flag in the mandatory label ACE mask means that subjects with a lower integrity level (in the access token) than the integrity level SID in the mandatory label on the object are restricted from getting generic write access to the object.

There is only one effective mandatory label on an object. If a security descriptor happens to get more than one mandatory label in the SACL, the first mandatory label ACE in the SACL is the effective label for the object.

For more information on the mandatory label ACE, see Windows Integrity Mechanism Resources.

Reading the mandatory label ACE

Windows Vista uses the security function, GetSecurityInfo, to read the mandatory label information from an object. GetSecurityInfo obtains the owner, group, DACL, or SACL information from an object. The SECURITY_INFORMATION parameter to GetSecurityInfo determines what part of the security descriptor is returned. Windows Vista defines a new security information value, LABEL_SECURITY_INFORMATION, which is used to return the mandatory label ACE from the SACL. If the call to GetSecurityInfo specifies SACL_SECURITY_INFORMATION, only the system audit ACEs in the SACL are returned, not the mandatory label ACE.

The access permission that is required to read the mandatory label ACE on an object is the READ_CONTROL standard access right. Normally, the ACCESS_SYSTEM_SECURITY access right is required to get or set information in the SACL. ACCESS_SYSTEM_SECURITY is granted only if the SE_SECURITY_NAME privilege is enabled in the access token. Reading the mandatory label from the SACL does not require SE_SECURITY_NAME privilege or the ACCESS_SYSTEM_SECURITY access right.

Setting the mandatory label ACE

Windows Vista uses the security function, SetSecurityInfo, to change the mandatory label information on an object. The object’s mandatory label is set by the security subsystem when the object is created. The SECURITY_INFORMATION parameter to SetSecurityInfo must include LABEL_SECURITY_INFORMATION in order to change the mandatory label in the security descriptor.

The mandatory label that is assigned at object creation is usually the correct integrity level for an object, and there is no need to change the mandatory label. However, there may be application design requirements to change an object's integrity level when the application is designed to support multiple client processes at different integrity levels.

The permissions that are required to change the mandatory label ACE in the SACL of a security descriptor is WRITE_OWNER. Writing the mandatory label to the SACL does not require SE_SECURITY_NAME privilege, or the ACCESS_SYSTEM_SECURITY access right. The integrity level in the mandatory label can be set to a value less than or equal to the subject’s integrity level.

The most common change is to lower the integrity level of an object to permit a lower integrity application process to have modify access. For example, an application at medium integrity level needs to synchronize with another application process running at low integrity level. The medium-integrity process creates a named mutex object and assigns it a mandatory label at low to permit a lower-integrity process to open the mutex to signal events.

Relabel privilege

The Windows integrity mechanism defines a new Windows security privilege, SE_RELABEL_NAME. When enabled in a security access token, the relabel security privilege allows the subject to set an object's mandatory label to a higher integrity level than the integrity level in the subject’s access token. The default security policy for Windows Vista does not assign this privilege to any user or group. The privilege is designed to address scenarios where an Administrator process running at a high integrity level needs to change or assign the mandatory label for objects at the system integrity level. Windows Vista does not have any tasks that require or use the relabel privilege.

How Windows assigns a mandatory label to objects

Windows assigns a mandatory label to a securable object when the object security descriptor is created. The integrity level on a new object is assigned in one of three ways:

  • The security subsystem assigns the object a mandatory label when the security descriptor is created for the object.
  • The creating process specifies an explicit mandatory label as security attributes when creating the object using a function, such as CreateFile.
  • The parent container defines an inheritable mandatory label ACE that applies to child objects that are created in the container.

The easiest way to understand how object integrity levels are assigned is to assume that every object is assigned a mandatory label with the same integrity level as the subject integrity level of the creating process (or thread). However, there are exceptions to the general idea based on object type and subject integrity level. The exceptions are the result of design choices that are necessary to support other system requirements for a consistent user experience when various security policies, such as UAC, are enabled or disabled.

Mandatory labels can be applied to all securable objects that have access control based on the security descriptor. There are many types of securable objects, including process and thread objects, named objects, and persistent objects such as files or registry keys. Windows Vista does not assign explicit mandatory labels to all object types when objects are created. The object types to which the security subsystem assigns mandatory labels at object creation are:

  • Process
  • Thread
  • Access token
  • Job

All other object types have either an implicit default or an inherited mandatory label. Recall that, during access token initialization, an integrity level is assigned to the security access token that is created during an interactive logon. The first process that is launched on behalf of a user logon is userinit.exe, which starts the shell process, explorer.exe. Userinit.exe is started by a system service (Winlogon) that uses a call to CreateProcessAsUser and passes in the access token for the interactive logon user.

CreateProcessAsUser creates a process object and an initial thread, among other things. When the process object is created, the security descriptor for that process is assigned the integrity level from the access token that is assigned as the primary access token to the new process. When userinit.exe calls CreateProcess to launch the shell, the process object for explorer.exe is initialized. The process object includes a security descriptor and primary access token. The mandatory label on the explorer.exe process is set to the integrity level of the creating process, userinit.exe, which is medium. The primary access token for explorer.exe is inherited from the creating parent process, userinit.exe, and has an integrity level of medium. When the explorer.exe process creates a new thread, the thread object is given a security descriptor, and the security subsystem assigns an integrity level to the thread object based on the integrity level of the creating process. The thread objects within the explorer.exe process are assigned an integrity level of medium, which is the integrity level of the primary access token of the creating process.

Note

An access token object is a securable object with its own security descriptor. The token’s security descriptor is used to determine allowed access during OpenProcessToken or OpenThreadToken functions. The access token object has a mandatory label in the security descriptor on the access token object. The access token also contains an integrity level SID in the access token groups list that represents the subject integrity level.

By always assigning mandatory labels to process, thread, token, and job objects, the integrity mechanism prevents processes for the same user at lower integrity levels from accessing these object types and modifying their content or behavior, such as injecting a DLL or impersonating a higher-level access token.

Default integrity level

Not all object types are assigned a mandatory label ACE in the security descriptor. If a mandatory label ACE is present in the security descriptor, that is called an explicit mandatory label. If no mandatory label ACE is present, the security subsystem uses an implicit default mandatory label for that object during the mandatory policy check. The default mandatory label assigns a medium integrity level for all securable objects. If a mandatory label is not defined in the security descriptor, the implicit default mandatory label applies to all object types.

The default object integrity level of medium, combined with the default mandatory policy of NO_WRITE_UP, restricts modify access to all objects by processes with a subject integrity level less than medium. The default mandatory label and policy prevent untrustworthy processes at low integrity from modifying any user or system files or registry keys on the system that may otherwise allow discretionary write access in the DACL.

The NTFS file system objects and registry keys are not automatically labeled when they are created. These objects do not have mandatory labels after upgrade from a previous version of Windows to Windows Vista. Files on non-NTFS file systems (CDFS or FAT32) that do not have security descriptors are not securable objects and do not have an integrity level. Every security descriptor must have an implicit mandatory label.

Processes with a subject integrity level at or above medium create files and registry keys without an explicit label. As a consequence, the file system and registry objects that are created by a high or system integrity level process have an implicit medium label. Applications that use mandatory labels can define explicit labels when creating objects. However, Windows Vista does not assign labels higher than medium integrity level to the file system or registry by default. That does not mean that these objects are necessarily open to modification by lower-integrity processes. The inherited (or default) discretionary access control list on file system or registry objects that were created by a high- or system-level process grants write access only to members of the Administrators group or to local System or service accounts.

A number of design constraints required using the default implicit mandatory label of medium, instead of assigning an explicit mandatory label based on the subject’s integrity level for most object types. A specific example is based on the ability to enable or disable User Account Control by using local security policy. When UAC is disabled, a user who is a member of the local Administrators group has all processes running with a full privilege access token at a high integrity level. If all objects are explicitly labeled at the subject’s integrity level, then all files such as documents and spreadsheets that the user creates would be assigned a high integrity level. The high label would seem appropriate, even though the inherited DACL permissions for the user profile provide sufficient access control for user access. However, if UAC is enabled by local computer or Group Policy, most processes run by the same user are assigned a filtered security access token at a medium integrity level. After UAC is enabled, the user would not be able to open files that were created when UAC was disabled. A medium-integrity application that tried to open the user's high-integrity documents would receive an Access Denied error.

If a process is running with a subject integrity level less than the default integrity level of medium, that process will have restricted access permissions to all objects that have an implicit medium integrity level. Processes with a low integrity level will not be able to modify any object with either an explicit or implicit integrity level of medium or higher, regardless of the access rights granted in the DACL to the security principal. Therefore, all objects that are created by a process with a subject integrity level less than the default level (medium) are explicitly labeled by the security subsystem. Access restrictions on low integrity processes are possible in Windows Vista because all applications generally run at the medium integrity level and the application compatibility issues are minimal. Applications that run correctly at low integrity generally require specific design changes to work correctly with restricted access. The design changes are discussed in the section below on Designing Applications to Run at a Low Integrity Level.

Labeling objects created by low subjects

Applications can be started using the CreateProcessAsUser function at a low integrity level. A low process is initialized by CreateProcessAsUser with the following integrity level information:

  • The new process object is created with a security descriptor containing a mandatory label with low integrity.
  • A new thread object is created for that process and with a security descriptor that contains a mandatory label with low integrity.
  • A primary access token is assigned to the new process. The access token object has a security descriptor with a mandatory label at low, and the access token contains a TokenIntegrityLevel with a low integrity SID that represents the subject integrity level.

Assume that the low integrity process is running, and that it wants to create a thread. To create a thread, it must open its own process object for write access to create a new thread object. If the mandatory label on the process object were medium, the low subject would fail to open the process and would not be able to create a new thread. Because the process object is also labeled at low integrity, the low subject is allowed to open the process for write access and to create a new thread object. The example shows why it is important that the mandatory labels on the process object, thread objects, and security access token be consistent at the same integrity level.

Note

This applies for all integrity levels, not only Low subjects.

Suppose that the low process creates a temporary file. The application calls CreateFile to create a new file, write some data, and close the file. Later, the low process wants to re-open the same file to append data. If the temporary file has an implicit default mandatory label at medium integrity level, the low process will not be able to reopen the file that it created earlier for modify access. The same issue could arise for any securable object that a subject with an integrity level below the default level of medium creates. Therefore, all securable objects created by a subject with an integrity level below the default level are automatically assigned an explicit mandatory label. In other words, all kernel objects, registry keys, and file system objects are explicitly labeled at low when the subject integrity level is low.

How to create an object with a specific mandatory label

Most Windows applications do not need to be “integrity-aware.” The security subsystem automatically creates objects and assigns them a mandatory label. Because most applications run at a medium integrity level, and the default object integrity level is medium, the integrity policy does not change the allowed access control for most applications. However, some applications, such as services, are designed to support client applications at different integrity levels. The service might be running at a higher integrity level than the client, and might want to label new objects created on behalf of the client explicitly at a lower integrity level. The integrity level of the object can be set by the creating process. The constraint is that the integrity level on the new object must be less than or equal to the integrity level of the creating process.

To create an object with a specific mandatory label

  1. Create an SDDL security descriptor that defines a low mandatory label, for example:
    #define LOW_INTEGRITY_SDDL_SACL_W L"S:(ML;;NW;;;LW)"
  2. Convert the SDDL string to a security descriptor using ConvertStringSecurityDescriptorToSecurityDescriptor.
  3. Assign the security descriptor with the low mandatory label to a security attributes structure.
  4. Pass the security attributes parameter to the call to create an object, such as CreateFile.

Mandatory label inheritance

Windows Vista does not explicitly label files and directories in the NTFS file system. As mentioned previously, the security subsystem uses an implicit mandatory label with a default level of medium for objects that do not have a mandatory label in the security descriptor.

Applications can be designed to run at a low integrity level. Protected Mode Internet Explorer is an example of a Windows Vista application that is designed to run at low integrity. Applications at low integrity might need folders in the file system where they can write temporary files or application data. In the case of Protected Mode Internet Explorer, the Temporary Internet File folder in the user’s profile is used. How can a low application write to a file system folder? The folder must be assigned an explicit mandatory label that permits write access from a low integrity process.

Depending on the application design, there might be other cooperating processes that add files to the folder used by the low integrity application. If the other processes are also running at low integrity, the files created by those processes are automatically assigned a low mandatory label. However, if the other partner process has a higher integrity, the partner process (a file synchronization service, or user agent) might create files in the low folder that are not automatically labeled at low. The partner process creates a medium file in the folder used by the low application, which the low application cannot modify or delete.

The integrity mechanism allows a folder with a low mandatory label to have child objects, files, and subfolders, each with a different, higher mandatory label because each file system object has a unique security descriptor. There are many scenarios where the intention is that, for a folder that is assigned a low mandatory label, all files in the folder must be assigned a low mandatory label so that a low process can modify them. The integrity mechanism supports this by enabling mandatory label ACEs to be inheritable from the parent container to sub-containers and child objects.

The mandatory label ACE type data structure contains an ACE header with an AceFlags field. The AceFlags field is used to define inheritance flags for the ACE type that are the same as inheritance flags for other ACE types, such as the Access Allowed ACE type that is used for discretionary access. Mandatory label ACEs can be defined as inheritable, for container inherit (CI) and/or object inherit (OI). Mandatory label ACEs cannot be inherit_only (IO). If there is an inheritable mandatory label ACE assigned to a container, the mandatory label applies to the container itself and to the child objects for which inheritance applies.

An example of an inheritable mandatory label is the low mandatory label on one of the folders created under every user profile: %USERPROFILE%\AppData\LocalLow. This folder is assigned a low mandatory label when the profile is initialized and intended as the top-level folder that is writeable by default by low-integrity applications. The following image shows the inheritable mandatory label on the AppData\LocalLow folder displayed using the Icacls command. For more information on how Icacls supports mandatory labels, see Appendix B: Icacls and File Integrity Levels.

The inheritance flags in the mandatory label indicate that the ACE is (OI) and (CI) ACE with a NO_WRITE_UP (NW) mandatory policy. All subfolders that are created under the AppData\LocalLow folder will inherit the inheritable label.

Figure 4   Inheritable low mandatory label

When a new file or subfolder is created from a medium process, the new object inherits the low mandatory label. In the following example, the command prompt is running in process with medium integrity level. A file, newfile.txt, and a new folder, Temp, is created in the LocalLow folder, and both objects inherit the low mandatory label from the parent container. Icacls indicates that the mandatory label is inherited with the (I) designation.

Figure 5   Inheriting a mandatory label on a child object

Inheritance for mandatory labels ensures consistency in the integrity level of objects that are created under a portion of the file system namespace.

Inheritance and explicit labels

Objects created in a container that has an inheritable mandatory label inherit the mandatory label from the container. However, the process that creates a new object such as a file can provide an explicit mandatory label in the security attributes parameter to the create function, such as CreateFile.

If the creating process provides an explicit label as a parameter to the object create function, the new object is assigned the explicit mandatory label provided by the caller and does not inherit from the parent container. The explicit mandatory label can have an integrity level no higher than the subject process creating the object. The integrity level in the explicit mandatory label provided by the subject might be higher than the integrity level in the parent container’s inheritable mandatory label.

Inherit-only restriction

Inherit-only (IO) is a flag in an access control entry that indicates that the ACE does not control access to the object to which it is attached. Inherit-only ACEs are usually assigned to container objects. The inherit-only ACE is not effective on the container itself; rather, it applies to child objects of the container. There is a restriction on subjects with an integrity level less than the default for setting INHERIT_ONLY labels on new objects. If the explicit label passed in for a new container object is an INHERIT_ONLY label with a level less than the default, the label is considered invalid and ignored. The rationale for this restriction is that a low subject creates a container and tries to set an INHERIT_ONLY label on the container at low. If the INHERIT_ONLY label were accepted, the effective integrity level for the container would be the implicit default level of medium.

Furthermore, subjects cannot define an INHERIT_ONLY label with an integrity level higher than the subject’s integrity level. For example, a medium subject cannot define an INHERIT_ONLY label with an integrity level of high.

Protected SACL and label inheritance

SDDL supports defining a protected SACL, which might include an explicit mandatory label. The protected SACL sets the SE_SACL_PROTECTED flag in the SECURITY_DESCRIPTOR_CONTROL field of the security descriptor. The logical separation of LABEL_SECURITY_INFORMATION and SACL_SECURITY_INFORMATION with respect to access rights is not complete with respect to how a protected SACL behaves. Mandatory labels are stored in the SACL. A protected SACL implies that the mandatory label is also protected.

If the SE_SACL_PROTECTED flag is set in the SECURITY_DESCRIPTOR_CONTROL, then the mandatory label is also protected.

  • If there is no mandatory label ACE in the protected SACL, an inheritable mandatory label ACE from the container is not applied (the new object has an implicit default mandatory label).
  • If there is a mandatory label ACE in the protected SACL, changes to the inheritable label ACE on the container do not affect this object.

For more information about SDDL, see Appendix A: SDDL for Mandatory Labels or Windows Integrity Mechanism Resources.

How access checks work with mandatory policy

The AccessCheck function enforces the mandatory policy. AccessCheck compares the specified security descriptor with the specified access token and indicates, in the AccessStatus parameter, whether access is granted or denied. The AccessCheck function first compares the integrity level in the ClientToken with the mandatory label in the SACL of pSecurityDescriptor to determine what access rights are not available, based on the mandatory policy. After the mandatory policy check, then AccessCheck compares the desired access against the access rights granted in the DACL.

The default mandatory policy prevents lower-integrity processes from gaining generic write access to higher-integrity objects. For example, by default a low-integrity process is denied generic write access to an object with a higher integrity level. If pSecurityDescriptor does not contain a mandatory ACE, an implicit mandatory ACE is assumed that assigns the object a medium integrity level. The GenericMapping parameter determines what access rights are associated with generic write access. If the GenericMapping parameter is all zeros, then the integrity check will not grant any specific access rights to a lower-integrity ClientToken. After the integrity check determines the generic access rights that are available to the caller based on the mandatory policy, the security descriptor’s DACL is compared with ClientToken to determine the remaining granted access rights.

User Interface Privilege Isolation (UIPI) and integrity

User Interface Privilege Isolation (UIPI) implements restrictions in the windows subsystem that prevents lower-privilege applications from sending window messages or installing hooks in higher-privilege processes. Higher-privilege applications are permitted to send window messages to lower-privilege processes. The restrictions are implemented in the SendMessage and related window message functions. Not all window messages that are sent from a lower-privilege process to a higher-privilege process are blocked. Generally, “read” type messages, for example WM_GETTEXT, can be sent from a lower-privilege to a higher-privilege window. However, write type messages, such as WM_SETTEXT, are blocked.

The UI privilege level is at the process level and applies to all windows created by the process. The USER subsystem initializes when the process makes the first call to the Windows graphics device interface (GDI). During process initialization, the USER subsystem calls in to the security subsystem to determine the integrity level assigned in the process's primary security access token. After the USER subsystem sets the UI privilege level during process initialization, it does not change. Setting the TokenIntegrityLevel for a thread to a lower value does not affect the UI privilege level of the process or any windows opened by that process or thread.

UIPI does not interfere with or change the behavior of window messaging between applications at the same privilege (or integrity) level. UIPI prevents lower-privilege processes from accessing higher-privilege processes by blocking the following behavior. A lower-privilege process cannot:

  • Perform a window handle validation of a process running with higher rights.
  • Use SendMessage or PostMessage to application windows running with higher rights. These APIs return success but silently drop the window message.
  • Use thread hooks to attach to a process running with higher rights.
  • Use journal hooks to monitor a process running with higher rights.
  • Perform dynamic link library (DLL) injection to a process running with higher rights.

With UIPI enabled, the following shared USER resources are still shared between processes at different privilege levels.

  • Desktop window, which actually owns the screen surface
  • Desktop heap read-only shared memory
  • Global atom table
  • Clipboard

Painting to the screen is another action that is not blocked by UIPI. The USER/graphics device interface (GDI) model does not allow control over painting surfaces. Therefore, it is possible for an application running with fewer rights to paint over the surface of the application window for an application running with higher rights.

UIAccess for UI automation applications

Microsoft UI automation is the Windows Vista model to support accessibility requirements with improvements over the earlier model, known as Microsoft Active Accessibility (MSAA). Applications designed to support accessible user experience control the behavior of other Windows applications on behalf of the user. When all applications (the automation client and server) are running as a standard user, that is, at a medium integrity level, the UIPI restrictions do not interfere with the UI automation model.

However, there may be times when an administrative user runs an application with elevated privilege based on UAC in Admin Approval Mode. The UI automation program will not be able to drive the graphics UI of elevated applications on the desktop without the ability to bypass restrictions that UIPI implements. The ability to bypass UIPI restrictions on SendMessage across privilege levels is available for UI automation programs using a special security attribute in the program’s application manifest, known as UIAccess.

The following is an example of an application manifest entry for a UIAccess program.

<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> 
  <security> 
    <requestedPrivileges> 
    <requestedExecutionLevel 
      level="asInvoker" 
      UIAccess="true" /> 
    </requestedPrivileges> 
  </security> 
</trustInfo>

By specifying UIAccess=”true” in the requestedPrivileges attribute, the application is stating a requirement to bypass UIPI restrictions on sending window messages across privilege levels. Windows Vista implements the following policy checks before starting an application with UIAccess privilege.

  • The application must have a digital signature that can be verified using a digital certificate that chains up to a trusted root in the local machine Trusted Root Certification Authorities certificate store.
  • The application must be installed in a local folder application directory that is writeable only by administrators, such as the Program Files directory. The allowed directories for UI automation applications are:
    • %ProgramFiles% and its subdirectories.
    • %WinDir% and its subdirectories, except a few subdirectories that are excluded because standard users have write access.

The %WinDir% subdirectories that are excluded subdirectories include:

  • \Debug
  • \PCHealth
  • \Registration
  • \System32\ccm
  • \System32\com
  • \System32\FxsTmp
  • \System32\Spool
  • \System32\Tasks

Windows Vista provides a security setting for the local computer policy and for Group Policy to adjust the requirement that UIAccess programs must be launched from secure locations. The setting is defined under the Security Options under the Local Policies for the Local Security Policies. The security policy is the following:

User Account Control: Only elevate UIAccess applications that are installed in secure locations

This setting is enabled by default. However, an administrator can disable it if there are situations where UIAccess applications (Accessible Technology) that must be launched from folders are not protected by administrator-only write access.

If the UI automation application that requests UIAccess meets the UIAccess setting requirements, then Windows Vista launches the application with the ability to bypass most of the UIPI restrictions. If the UI automation application does not meet the security restrictions, the application will be launched without UIAccess rights and can interact only with applications at the same or lower privilege level.

A process that is launched with UIAccess rights:

  • Has the ability to set the foreground window.
  • Can drive any application window using SendInput function.
  • Has read input for all integrity levels using low-level hooks, raw input, GetKeyState, GetAsyncKeyState, and GetKeyboardInput.
  • Can set journal hooks.
  • Uses AttachThreadInput to attach a thread to a higher integrity input queue

Applications that are launched with UIAccess rights for a standard user are assigned a slightly higher integrity level value in the access token. The access token integrity level for the UIAccess application for a standard user is the value of medium integrity level, plus an increment of 0x10. The higher integrity level for UIAccess applications prevents other processes on the same desktop at the medium integrity level from opening the UIAccess process object.