Kernel Object Security Descriptor with NULL DACL

RLWA32 40,771 Reputation points
2020-10-16T14:15:56.65+00:00

I recently noticed that an unnamed event created by CreateEvent received a security descriptor with a NULL DACL. The call to CreateEvent passed nullptr as the lpEventAttributes parameter.

I expected the event to receive a security descriptor based on the default dacl contained in the process token. After all, the documentation says "If lpEventAttributes is NULL, the event gets a default security descriptor. The ACLs in the default security descriptor for an event come from the primary or impersonation token of the creator." But this was not the case. The NULL DACL could also be observed using Process Explorer.

So is the documentation incorrect?

Sample code to see this result is -

   #define WIN32_LEAN_AND_MEAN  
   #include <Windows.h>  
   #include <AclAPI.h>  
   #include <sddl.h>  
     
   #include <stdio.h>  
   #include <tchar.h>  
     
   void PrintDefaultDACL();  
   void PrintDACL(HANDLE h);  
     
   int main()  
   {  
   _tprintf(_T("\nPrint Default DACL from process token\n"));  
   PrintDefaultDACL();  
     
   // Named event receives default security descriptor base on primary or impersonation token  
   _tprintf(_T("\nPrint DACL for named kernel object\n"));  
   HANDLE h1 = CreateEvent(nullptr, FALSE, FALSE, _T("Test"));  
   PrintDACL(h1);  
   CloseHandle(h1);  
     
   // Unnamed event receives security descriptor with a NULL DACL  
   _tprintf(_T("\nPrint DACL for unnamed kernel object\n"));  
   HANDLE h2 = CreateEvent(nullptr, FALSE, FALSE, nullptr);  
   PrintDACL(h2);  
   CloseHandle(h2);  
     
   return 0;  
   }  
     
   void PrintDefaultDACL()  
   {  
   HANDLE hToken = NULL;  
     
   if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))  
   {  
   DWORD dwBytes = 0;  
   PTOKEN_DEFAULT_DACL pDefaultDacl = nullptr;  
   if (!GetTokenInformation(hToken, TokenDefaultDacl, pDefaultDacl, 0, &dwBytes) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)  
   {  
   pDefaultDacl = (PTOKEN_DEFAULT_DACL)LocalAlloc(LPTR, dwBytes);  
   if (GetTokenInformation(hToken, TokenDefaultDacl, pDefaultDacl, dwBytes, &dwBytes))  
   {  
   PSECURITY_DESCRIPTOR pSD = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);  
   if (InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))  
   {  
   if (SetSecurityDescriptorDacl(pSD, TRUE, pDefaultDacl->DefaultDacl, FALSE))  
   {  
   LPTSTR pszSD = nullptr;  
   ULONG uLen = 0;  
   if (ConvertSecurityDescriptorToStringSecurityDescriptor(pSD, SDDL_REVISION_1, DACL_SECURITY_INFORMATION, &pszSD, &uLen))  
   {  
   _tprintf_s(_T("%s\n"), pszSD);  
   LocalFree(pszSD);  
   }  
   }  
   }  
   LocalFree(pSD);  
   }  
   LocalFree(pDefaultDacl);  
   }  
   CloseHandle(hToken);  
   }  
   }  
     
   void PrintDACL(HANDLE h)  
   {  
   PSECURITY_DESCRIPTOR pSD = nullptr;  
   PACL pDacl = nullptr;  
   if (GetSecurityInfo(h, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, nullptr, nullptr, &pDacl, nullptr, &pSD) == ERROR_SUCCESS)  
   {  
   LPTSTR pszSD = nullptr;  
   ULONG ulen = 0;  
   _tprintf_s(_T("Pointer to DACL in security descriptor is 0x%p\n"), pDacl);  
   if (ConvertSecurityDescriptorToStringSecurityDescriptor(pSD, SDDL_REVISION_1, DACL_SECURITY_INFORMATION, &pszSD, &ulen))  
   {  
   _tprintf_s(_T("DACL: %s\n"), pszSD);  
   LocalFree(pszSD);  
   }  
   LocalFree(pSD);  
   }  
   }  
Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,429 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,544 questions
{count} votes

Accepted answer
  1. Rita Han - MSFT 2,161 Reputation points
    2020-10-19T03:06:02.003+00:00

    Hello @RLWA32 ,

    Thanks for binging this to our attention.

    I can reproduce this issue.

    "If lpEventAttributes is NULL, the event gets a default security descriptor." (CreateEvent()) This statement seems misleading. I've reported it internally and will update here if there is any progress.

    Thank you!


0 additional answers

Sort by: Most helpful