Vista Improves Security Through Private Object Namespaces
You can protect Windows kernel objects such as events and mutexes by using security descriptors, but prior to Windows Vista you couldn't secure the actual names of the kernel objects. Building on the concept of namespaces that are used to separate Terminal Service sessions, Windows Vista allows you to define, secure, and use custom namespaces to prevent malicious applications from denying access to kernel object functionality.
Figure 1. Private Object Namespace
In Figure 1, the malicious application can create a namespace and kernel object of the same name, but it will not affect the use of kernel objects to synchronize data exchanges between the two server processes, which have different SIDs.
Using Private Namespaces
The syntax for using private namespaces is fairly simple. To create a server process (which would typically be in charge of creating the kernel objects and now has the added responsibility of securing them with a namespace), you can use the following code:
//create SECURITY_ATTRIBUTES for namespace boundary
SECURITY_ATTRIBUTES saKernelObjectSecurity;
saKernelObjectSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
//use the default security descriptor of the calling process
saKernelObjectSecurity.lpSecurityDescriptor = NULL;
saKernelObjectSecurity.bInheritHandle = TRUE;
//create boundary
HANDLE hBoundaryDescriptor =
CreateBoundaryDescriptor(_T("MC_BoundaryDescriptor"), 0);
if (NULL == hBoundaryDescriptor){
printf("CreateBoundaryDescriptor failed. %d", ::GetLastError());
return 1;
}
//get the local admin SID and add this to the boundary descriptor
PSID pLocalAdmin;
if (FALSE == ConvertStringSidToSid(_T("LA"), &pLocalAdmin)){
printf("ConvertStringSidToSid failed. %d", ::GetLastError());
return 1;
}
//add SID to boundary
BOOL res = AddSIDToBoundaryDescriptor(&hBoundaryDescriptor,
pLocalAdmin);
LocalFree(pLocalAdmin); //done with SID - free memory
if (FALSE == res){
printf("AddSIDToBoundaryDescriptor failed. %d", ::GetLastError());
return 1;
}
//create the namespace
HANDLE hNamespace = CreatePrivateNamespace(NULL, hBoundaryDescriptor,
_T("MC"));
if (NULL == hNamespace){
printf("CreatePrivateNamespace failed. %d", ::GetLastError());
return 1;
}
//create mutex inside the namespace
HANDLE hMutex = CreateMutex(&saKernelObjectSecurity, FALSE,
_T("MC\\MyMutex"));
if (NULL == hMutex){
printf("CreateMutex failed. %d", ::GetLastError());
return 1;
}
else{
printf("Successfully created mutex in private namespace");
}
printf("Press any key to quit");
char c;
gets_s(&c, 1);
CloseHandle(hMutex);
ClosePrivateNamespace(hNamespace, PRIVATE_NAMESPACE_FLAG_DESTROY);
return 0;
The code is relatively simple. It creates a namespace boundary with the default security attributes of the process, adds the SID of the local admin group to the boundary, and creates a namespace using the boundary. Once the boundary has been created, a kernel object can be created with the standard kernel functions—the only modification is the addition of the namespace prefix in the object's name.
The code required to open kernel objects in the namespace is almost identical, with the only differences being the use of the OpenNamespace function instead of the CreatePrivateNamespace. Once the private namespace has been opened, new kernel objects can be created with the prefix and existing objects can be opened using the prefix.
The key security feature is the namespace boundary and the associated SID—if the calling process is not within the group defined by the SID, a namespace cannot be created using the boundary. As the identity of a namespace is defined by both its boundary and string name, a process running at a lower privilege cannot conduct a kernel object name DOS attack.
Private Object Namespaces: Small But Crucial
While the average application developer isn't consumed by worry and stress about kernel object name squatting ruining his or her code-cutting career, the need for applications to achieve high-performance synchronization of the data they exchange is a real issue. Prior to private object namespaces, the possibility of malicious applications interfering with software systems such as virus scanners and DRM solutions was very real. As the fruits of Microsoft's big security push in the early part of the decade come to fruition in major product releases, the range of security-related functionality being released is certainly increasing, and private object namespaces are a small but crucial part of this push.
PON are great, but I still have not been able to find an explanation for the Vista behavior I describe here:
ReplyDeletehttp://rdn-consulting.com/blog/2007/08/20/kernel-object-namespace-and-vista/
Any ideas?
Where are those mutexes physically stored anyways? Or do you have to reboot to get rid of wandering mutexes
ReplyDelete