Securing WMI Namespaces

On Windows NT, 2000, and XP platforms, each user and group is given unique security identifiers (SIDs). A SID is a variable length value that is assigned to a user or group account when such an account is created. SIDs are always unique within the scope of the account to which they belong. Thus, a SID for a local account is always unique within the computer system to which the account belongs, and a SID for a domain account is unique within that domain. SIDs are also unique in time, meaning that the system does not reuse the SID values under any circumstances. Therefore, if an account is deleted and then recreated, it is assigned a brand new SID despite the fact that the account name stays the same.

SIDs are used extensively by the Windows security framework. For instance, each access token—an object that described the security context of a process or a thread—has an embedded SID, which represents a user or a group associated with the token. Another security structure—the security descriptor (SD), which contains all relevant security information for a securable object—also contains SIDs that identify the owner of the associated object and the primary group of the owner. Finally, access control entries (ACEs), which govern access to a particular securable object, house SIDs that identify the users and groups to whom access is granted or denied.

A SD is, perhaps, the most notable structure within the Windows security model. As its name implies, it describes the security-related traits of a given object, such as its ownership and access restrictions. A Security Descriptor structure (SECURITY_DESCRIPTOR), consists of the following elements:

• SID of the object's owner

• SID of the group to which the object's owner belongs

• Discretionary access control list (DACL) that specifies the levels of access that particular users or groups may have to the object

• System access control list (SACL) that controls the generation of the audit messages, logging the attempts to access the object

• Security descriptor control information, packaged into the SECURITY_DESCRIPTOR_CONTROL structure. This is a set of bit flags that qualify the semantics of the individual components of the security descriptor.

An access control list (ACL) is a list of zero or more access control entries (ACEs) that are used as a basis for determining the access control and audit rights for a particular security principal. Each ACE contains the following information:

• A SID that uniquely identifies a security principal (user or group) to which the ACE applies.

• An access mask—a 32-bit value that specifies the rights that are denied or allowed by the ACE.

• A flag that indicates the type of the ACE: access-denied ACE, accessallowed ACE, or system-audit ACE.

• Bit flags that specify whether the child objects are allowed to inherit the ACE from the primary object to which the ACE applies.

The access rights, specified by the access mask field, can be divided into four categories: generic, standard, SACL access, and Directory Services (DS) access rights.

A combination of access rights is packaged into a 32-bit field so that the loworder 16 bits of the access mask reflect the object-specific rights, the next 7 bits are reserved for the standard rights, bit 23 represents the right to access the SACL, and finally, the 4 high-order bits are used for the generic access rights.

Another structure that plays a very important role within the Windows security infrastructure is the access token. An access token is assigned to a user whenever a user logs into the system. When a logon session is initiated, the system authenticates the user's password against the security database and issues an access token, which subsequently gets attached to every process executed on behalf of the user. Then, the system uses the access token to establish the user's identity and level of access every time the user issues a request to access a securable object. An access token contains the following information:

• A SID of the user's account.

• A collection of SIDs for each group to which the user belongs.

• A logon SID that uniquely identifies the logon session.

• A list of privileges granted to a user or the user's groups.

• An owner SID.

• A SID of the primary group.

• The source of the access token.

• The flag that indicates whether it is a primary or impersonation token. The primary token is created by the Windows executive layer and typically represents the default security settings for the process. The impersonation token is created to capture the security settings of an arbitrary process, thus allowing the current process to "impersonate" the latter.

• A list of restricting SIDs. The restricting SIDs are used when a process is running under a restricted security context. In such cases, the system checks not only the primary SID but also the restricted SIDs before it grants access to a securable object.

• Current impersonation levels.

• Miscellaneous statistics.

Besides carrying the user's identity, an access token also includes all privileges granted to a user or the user's groups. A privilege is a right granted to a security principal that enables the latter to perform certain administrative functions on a local computer. Such administrative functions may include shutting down the system, modifying the system's date and time settings, and loading and unloading the device drivers. As opposed to access rights, which control access to securable objects, privileges govern access to system resources and tasks.

Each user and group account is associated with a set of privileges that is stored in Windows security database. Whenever a user logs into a system, the privileges are incorporated into the user's access token. Note that such privileges will only apply to a local computer system, since domain accounts may have different sets of privileges on different machines. When a user attempts to perform an operation that is marked as privileged, the system checks the privileges embedded into the user's access token. If the appropriate privileges are granted and enabled, the system allows the operation; otherwise the operation fails. Interestingly, the privileges, even if granted, are disabled by default so that the user has to explicitly enable them prior to requesting a privileged operation. A privilege can be enabled using the AdjustTokenPrivileges function of the Win32 API.

To summarize, every access check carried out by the system essentially boils down to matching the user's security information, which is encoded into the access token, against the SD of a securable object. Thus, in order to secure an arbitrary resource, the resource has to be assigned an appropriate SD that incorporates the necessary ACEs. Securing the WMI namespaces is no exception. In fact, each namespace is associated with an SD that carries all the security information needed to ensure the proper access checks. The SD of a namespace can be manipulated using the WMI MMC snap-in.
Using the security configuration page of the snap-in is as trivial as using the Properties dialog when securing files. All you need to do is select a namespace to secure and modify the associated user's or group's permissions.

In the true spirit of WMI, the SD for a namespace can also be retrieved and manipulated programmatically. A system class called __SystemSecurity provides such programmatic access to namespace security settings. This class has the following definition:

class __SystemSecurity {
[Static] uint32 GetSD([out] uint8 SD[]);
[Static] uint32 Get9XUserList([out] __ntlmuser9x ul[]);
[Static] uint32 SetSD([in] uint8 SD[]);
[Static] uint32 Set9XUserList([in] __ntlmuser9x ul[]);
[Static] uint32 GetCallerAccessRights([out] sint32 rights);

This class is fairly unusual because it does not contain any properties. Rather than exposing all of the SD or its individual parts as properties of an object, the designers of WMI turned the __SystemSecurity class into a singleton and equipped it with a number of static methods for reading the security descriptor and writing the modified version of it back to the CIM Repository. As you can see in the definition above, the class has the following methods:

• GetSD: Used to get an SD associated with a namespace to which the user is currently connected. The SD is returned as an array of unsigned bytes and it has to be cast into an appropriate structure to be manipulated. This method is only available on Windows NT, Windows 2000, and Windows XP platforms.

• Get9XUserList: Used to retrieve a list of users who are allowed to access the namespace. This method is only available on Windows 9X platforms, and it returns an array of instances of the __Win9XUser class. This is done to simulate the functionality of SDs on Windows 9X systems.

• SetSD: Writes the modified SD for a namespace back to the CIM Repository. The SD is represented by an array of unsigned bytes. This method is only available on Windows NT, Windows 2000, and Windows XP platforms.

• Set9XUserList: Writes the list of users who are allowed to access the namespace back to the CIM Repository. This method is only available on Windows 9X platforms.

• GetCallerAccessRights: Retrieves the access masks for a client process. The mask is a 32-bit value where each bit represents an individual access right. This method is available on all Windows platforms.

Unfortunately, the methods of the __SystemSecurity class can only be used to retrieve or save an SD, but they cannot be utilized for SD manipulation. Also, it is not recommended to manipulate the SD byte array directly. Instead, the functions of the Win32 API should be used to extract or set the individual values within an SD. For instance, to convert a binary SD into a human-consumable form (an SDDL string representation), you may use the ConvertSecurityDescriptorToStringSecurityDescriptor function (that is, if you manage to spell the name of the function correctly).

By default, the security settings for a namespace are inherited by all its children namespaces. This means that by setting the permissions for the \root namespace, you may have these permissions propagated to each WMI namespace. You can also change the default behavior and turn the inheritance off by setting the CONTAINER_INHERIT_ACE (0x2) flag in the ACEs that are associated with a security descriptor for a namespace. It is also possible to determine whether a particular ACE is inherited by checking for the INHERITED_ACE (0x10) flag within the ACE for a namespace.

Source of Information : Dot NET System Management Services - Apress


Subscribe to Developer Techno ?
Enter your email address:

Delivered by FeedBurner