Access Control Lists (ACLs)

Access Control Lists (ACLs) are fundamental components of the Windows security model. They define the permissions granted to users and groups for specific 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).

Understanding ACLs and ACEs

An ACL is essentially a data structure that contains a list of ACEs. Each ACE specifies a security principal (like a user or group) and the type of access that principal is granted or denied to the object. There are two primary types of ACLs:

Access Control Entries (ACEs)

Each ACE within an ACL has the following key components:

Important: Deny ACEs take precedence over Allow ACEs. If a user is a member of multiple groups, and one group has a Deny ACE while another has an Allow ACE for the same resource, the Deny ACE will be enforced.

ACL Structure in the Kernel

Internally, the Windows kernel represents ACLs using structures like ACL and ACE_HEADER. The DACL is typically associated with an object's security descriptor, which is managed by the kernel's Security Reference Monitor (SRM).

When a process attempts to access a securable object, the kernel's security subsystem walks the object's ACL. It evaluates the ACEs in a specific order:

  1. All explicit Deny ACEs for the user/group are checked first. If a match is found, access is denied.
  2. All explicit Allow ACEs for the user/group are checked. If a match is found, access is granted.
  3. If no explicit ACE matches, the system checks for inherited ACEs from parent objects.
  4. If access is still not determined, the default system policy is applied (which usually results in denial).

// Simplified representation of an ACL structure (conceptual)
typedef struct _ACL {
    USHORT AclRevision;
    USHORT AclSize;
    USHORT AceCount;
    USHORT Sbz1;
    ULONG  SaclArrayOffset; // Offset to the first ACE
    ULONG  RmDaclInfo;      // Flags related to DACL
} ACL;

// Simplified representation of an ACE Header
typedef struct _ACE_HEADER {
    UCHAR  AceType;
    UCHAR  AceFlags;
    USHORT AceSize;
} ACE_HEADER;

// Simplified representation of an ACCESS_ALLOWED_ACE
typedef struct _ACCESS_ALLOWED_ACE {
    ACE_HEADER Header;
    ACCESS_MASK AccessMask;
    ULONG SidStart; // Offset to the SID in the Trustee
    // Followed by SID and optional compound ACE data
} ACCESS_ALLOWED_ACE;
            

Object Security Descriptors

ACLs are part of a larger security construct called the Security Descriptor. A security descriptor for an object contains:

Developers interacting with ACLs programmatically typically use the Win32 API functions like GetSecurityInfo, SetSecurityInfo, SetEntriesInAcl, and structure manipulation with PSECURITY_DESCRIPTOR, PACL, and PACCESS_ALLOWED_ACE.

Key Concepts and Best Practices

Understanding and effectively managing ACLs is crucial for maintaining a secure and robust Windows environment. The kernel's role is to enforce these permissions rigorously and efficiently.