Access Control Lists (ACLs)
Access Control Lists (ACLs) are fundamental to Windows security. They define the permissions that users and groups have to access securable objects such as files, directories, registry keys, and processes. Each ACL is associated with an object and contains a list of Access Control Entries (ACEs).
Core Concepts
- Securable Objects: Any resource that can have its access controlled by the system.
- Access Control Entry (ACE): A list entry that specifies the type of access (allow or deny) for a specific trustee (user or group) to an object.
- Trustee: A security principal, which can be a user account, a group account, or a service account.
- Permissions: Specific rights granted or denied by ACEs, such as read, write, execute, delete, or full control.
Types of ACLs
Windows utilizes two main types of ACLs:
- Discretionary Access Control List (DACL): This is the primary ACL that defines who has what access to an object. If an object has no DACL, it typically defaults to allowing all access to the owner. An empty DACL grants no access to anyone.
- System Access Control List (SACL): This ACL is used for auditing purposes. It specifies which access attempts (successful or failed) should be logged in the security event log.
Structure of an ACL
An ACL is a data structure that contains:
- ACL revision information.
- A count of ACEs.
- A list of ACEs.
Each ACE within an ACL typically consists of:
- ACE type (Allow or Deny).
- ACE flags (e.g., inherited, critical).
- Access mask (a bitmask defining the specific permissions).
- A pointer to the trustee SID (Security Identifier).
Working with ACLs in Win32
The Win32 API provides a rich set of functions for manipulating ACLs. Key functions include:
GetSecurityInfoandSetSecurityInfo: For retrieving and setting security descriptors (which contain ACLs) on objects.GetNamedSecurityInfoandSetNamedSecurityInfo: Similar to the above but work with object names.GetAclInformationandSetAclInformation: For accessing and modifying specific ACL properties.AddAccessAllowedAce,AddAccessDeniedAce,AddAccessAllowedAceEx,AddAccessDeniedAceEx: For adding ACEs to an ACL.CreateSecurityDescriptor,MakeAbsoluteSD,MakeSelfRelativeSD: For managing security descriptors.
Example: Adding an Allow ACE
This simplified example illustrates the concept of adding an ACE. In a real application, error handling and detailed security descriptor management would be crucial.
void GrantReadAccessToFile(HANDLE hFile, PSID pUserSid) {
PSECURITY_DESCRIPTOR pSD = NULL;
PACL pDacl = NULL;
DWORD dwAclSize = 0;
BOOL bDaclPresent = FALSE;
BOOL bDaclDefaulted = FALSE;
EXPLICIT_ACCESS ea;
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
PSID pAdminSid = NULL;
// Get existing security descriptor
if (GetSecurityInfo(hFile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDacl, NULL, &pSD) != ERROR_SUCCESS) {
// Handle error
return;
}
// Get ACE information for Read access
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = FILE_GENERIC_READ;
ea.grfAccessMode = SET_ACCESS;
ea.dwInheritance = NO_INHERITANCE;
ea.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea.Trustee.ptstrName = (LPWSTR)pUserSid; // Assign the user SID
// Build a new DACL
if (SetEntriesInAcl(&ea, 1, pDacl, &pDacl) != ERROR_SUCCESS) {
// Handle error
LocalFree(pSD);
return;
}
// Set the new DACL on the file
if (SetSecurityInfo(hFile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pDacl, NULL) != ERROR_SUCCESS) {
// Handle error
}
LocalFree(pSD);
if (pDacl != NULL) LocalFree(pDacl); // Free if allocated by SetEntriesInAcl
}
Inheritance
ACLs can also be inherited. Child objects can inherit ACEs from their parent containers. This is controlled by flags within the ACEs themselves. Inheritance helps in managing permissions across a directory structure efficiently.
Best Practices
- Principle of Least Privilege: Grant only the necessary permissions to users and groups.
- Use Groups: Assign permissions to groups rather than individual users to simplify management.
- Understand Deny ACEs: Deny ACEs always override Allow ACEs. Use them cautiously.
- Audit Important Objects: Configure SACLs to monitor access to sensitive resources.
Mastering ACLs is crucial for secure application development and system administration in Windows environments. The Win32 API provides the tools necessary to programmatically manage these powerful security constructs.