| Glossary |
Standard Attribute Header?
The security descriptor can be summarised as:
| Component | Description | ||
|---|---|---|---|
| Header | Offsets to various structures | ||
| Audit ACL | ACE | SID | ACEs for the Audit ACL |
| Permissions ACL | ACE | SID | ACEs for the Permissions ACL |
| ACE | SID | ||
| ACE | SID | ||
| SID (User) | The owner of this object | ||
| SID (Group) | |||
The security descriptor is necessary to prevent unauthorised access to files. It stores information about:
As defined in $AttrDef, this attribute has a no minimum or maximum size.
| Offset | Size | Description |
|---|---|---|
| 0x00 | 1 | Revision (a) |
| 0x01 | 1 | Padding |
| 0x02 | 2 | Control Flags (b) |
| 0x04 | 4 | Offset to User SID |
| 0x08 | 4 | Offset to Group SID |
| 0x0C | 4 | Offset to SACL |
| 0x10 | 4 | Offset to DACL |
(a) 0x1 for now
(b) Usually 0x4 (DACL Present), or 0x14 (DACL Present + SACL Present). See Flags below.
(c) This refers to the Auditing ACL
(d) This refers to the Permissions ACL
| Offset | Size | Description |
|---|---|---|
| 0x00 | 1 | ACL Revision |
| 0x01 | 1 | Padding (0x00) |
| 0x02 | 2 | ACL size |
| 0x04 | 2 | ACE count |
| 0x06 | 2 | Padding (0x0000) |
The Access Control List (ACL) contains one or many ACEs.
The ACL revision is currently 0x02, on my machine.
The Win32 APIs suggest that 0x01 and 0x06 contain padding 0x00's for alignment
purposes.
| Offset | Size | Description |
|---|---|---|
| 0x00 | 1 | Type |
| 0x01 | 1 | Flags |
| 0x02 | 2 | Size |
| 0x04 | 4 | Access mask |
| 0x08 | V | SID |
The currently implemented (in NT) Types are:
| Value | Description |
|---|---|
| 0x00 | Access Allowed |
| 0x01 | Access Denied |
| 0x02 | System Audit |
Flags is a bit field. The possible values of Flags depend on the value of Type. When applied to a directory, Access Allowed or Access Denied can have flags of
| Value | Description |
|---|---|
| 0x01 | Object inherits ACE |
| 0x02 | Container inherits ACE |
| 0x04 | Don't propagate 'Inherit ACE' |
| 0x08 | Inherit only ACE |
If the Type is System Audit, then the flags can be
| Value | Description |
|---|---|
| 0x40 | Audit on Success |
| 0x80 | Audit on Failure |
The Access Mask / Rights is a bit field enumerating all the (dis)allowed actions.
| Bit (Range) | Meaning | Description / Examples |
|---|---|---|
| 0 - 15 | Object Specific Access Rights | Read data, Execute, Append data |
| 16 - 22 | Standard Access Rights | Delete, Write ACL, Write Owner |
| 23 | Can access security ACL | |
| 24 - 27 | Reserved | |
| 28 | Generic ALL (Read, Write, Execute) | Everything below |
| 29 | Generic Execute | All things necessary to execute a program |
| 30 | Generic Write | All things necessary to write to a file |
| 31 | Generic Read | All things necessary to read a file |
A typical SID looks like: S-1-5-21-646518322-1873620750-619646970-1110
It's composed of 'S-p-q-r-s-t-u-v'
| S | Security |
| p | Revision number (currently 1) |
| q | NT Authority. This number is divided into 6 bytes (48 bit big-endian number). |
| r - v | NT Sub-authorities (there can be many of these) |
On disk the SID is stored as follows:
S-1-5-21-646518322-1873620750-619646970-1110
in hex:
S-1-5-15-26891632-6fad2f0e-24ef0ffa-456 (5 Sub-authorities)
| 0x00 | 01 | 05 | 00 | 00 | 00 | 00 | 00 | 05 |
| 0x08 | 15 | 00 | 00 | 00 | 32 | 16 | 89 | 26 |
| 0x10 | 0e | 2f | ad | 6f | fa | 0f | ef | 24 |
| 0x18 | 56 | 04 | 00 | 00 |
NB This is a variable length structure. The could have been more, or fewer, sub-authorities making the structure larger, or smaller.
| Flag | Description |
|---|---|
| 0x0001 | Owner Defaulted |
| 0x0002 | Group Defaulted |
| 0x0004 | DACL Present |
| 0x0008 | DACL Defaulted |
| 0x0010 | SACL Present |
| 0x0020 | SACL Defaulted |
| 0x0100 | DACL Auto Inherit Req |
| 0x0200 | SACL Auto Inherit Req |
| 0x0400 | DACL Auto Inherited |
| 0x0800 | SACL Auto Inherited |
| 0x1000 | DACL Protected |
| 0x2000 | SACL Protected |
| 0x4000 | RM Control Valid |
| 0x8000 | Self Relative |
This boolean flag, when set, indicates that the SID pointed to by the Owner field was provided by a defaulting mechanism rather than explicitly provided by the original provider of the security descriptor. This may affect the treatment of the SID with respect to inheritence of an owner.
This boolean flag, when set, indicates that the SID in the Group field was provided by a defaulting mechanism rather than explicitly provided by the original provider of the security descriptor. This may affect the treatment of the SID with respect to inheritence of a primary group.
This boolean flag, when set, indicates that the security descriptor contains a discretionary ACL. If this flag is set and the Dacl field of the SECURITY DESCRIPTOR is null, then a null ACL is explicitly being specified.
This boolean flag, when set, indicates that the ACL pointed to by the Dacl field was provided by a defaulting mechanism rather than explicitly provided by the original provider of the security descriptor. This may affect the treatment of the ACL with respect to inheritence of an ACL. This flag is ignored if the DaclPresent flag is not set.
This boolean flag, when set, indicates that the security descriptor contains a system ACL pointed to by the Sacl field. If this flag is set and the Sacl field of the SECURITY DESCRIPTOR is null, then an empty (but present) ACL is being specified.
This boolean flag, when set, indicates that the ACL pointed to by the Sacl field was provided by a defaulting mechanism rather than explicitly provided by the original provider of the security descriptor. This may affect the treatment of the ACL with respect to inheritence of an ACL. This flag is ignored if the SaclPresent flag is not set.
This boolean flag, when set, indicates that the security descriptor is in self-relative form. In this form, all fields of the security descriptor are contiguous in memory and all pointer fields are expressed as offsets from the beginning of the security descriptor.
The SID structure is a variable-length structure used to uniquely identify
users or groups. SID stands for security identifier.
The standard textual representation of the SID is of the form:
S-R-I-S-S...
Where:
- The first "S" is the literal character 'S' identifying the following
digits as a SID.
- R is the revision level of the SID expressed as a sequence of digits
either in decimal or hexadecimal (if the later, prefixed by "0x").
- I is the 48-bit identifier_authority, expressed as digits as R above.
- S... is one or more sub_authority values, expressed as digits as above.
Example SID; the domain-relative SID of the local Administrators group on
Windows NT/2k:
S-1-5-32-544
This translates to a SID with:
revision = 1,
sub_authority_count = 2,
identifier_authority = {0,0,0,0,0,5}, SECURITY_NT_AUTHORITY
sub_authority[0] = 32, SECURITY_BUILTIN_DOMAIN_RID
sub_authority[1] = 544 DOMAIN_ALIAS_RID_ADMINS
ACE Types
ACCESS_MIN_MS_ACE_TYPE = 0
ACCESS_ALLOWED_ACE_TYPE = 0
ACCESS_DENIED_ACE_TYPE = 1
SYSTEM_AUDIT_ACE_TYPE = 2
SYSTEM_ALARM_ACE_TYPE = 3 Not implemented as of Win2k.
ACCESS_MAX_MS_V2_ACE_TYPE = 3
ACCESS_ALLOWED_COMPOUND_ACE_TYPE = 4
ACCESS_MAX_MS_V3_ACE_TYPE = 4
The following are Win2k only.
ACCESS_MIN_MS_OBJECT_ACE_TYPE = 5
ACCESS_ALLOWED_OBJECT_ACE_TYPE = 5
ACCESS_DENIED_OBJECT_ACE_TYPE = 6
SYSTEM_AUDIT_OBJECT_ACE_TYPE = 7
SYSTEM_ALARM_OBJECT_ACE_TYPE = 8
ACCESS_MAX_MS_OBJECT_ACE_TYPE = 8
ACCESS_MAX_MS_V4_ACE_TYPE = 8
This one is for WinNT&2k.
ACCESS_MAX_MS_ACE_TYPE = 8
The ACE flags (8-bit) for audit and inheritance
SUCCESSFUL_ACCESS_ACE_FLAG is only used with system audit and alarm ACE
types to indicate that a message is generated (in Windows!) for successful
accesses.
FAILED_ACCESS_ACE_FLAG is only used with system audit and alarm ACE types
to indicate that a message is generated (in Windows!) for failed accesses.
The inheritance flags.
OBJECT_INHERIT_ACE = 0x01
CONTAINER_INHERIT_ACE = 0x02
NO_PROPAGATE_INHERIT_ACE = 0x04
INHERIT_ONLY_ACE = 0x08
INHERITED_ACE = 0x10 Win2k only
VALID_INHERIT_FLAGS = 0x1f
The audit flags.
SUCCESSFUL_ACCESS_ACE_FLAG = 0x40
FAILED_ACCESS_ACE_FLAG = 0x80
The access mask defines the access rights.
The standard rights.
DELETE = 0x00010000
READ_CONTROL = 0x00020000
WRITE_DAC = 0x00040000
WRITE_OWNER = 0x00080000
SYNCHRONIZE = 0x00100000
STANDARD_RIGHTS_REQUIRED = 0x000f0000
STANDARD_RIGHTS_READ = 0x00020000
STANDARD_RIGHTS_WRITE = 0x00020000
STANDARD_RIGHTS_EXECUTE = 0x00020000
STANDARD_RIGHTS_ALL = 0x001f0000
The access system ACL and maximum allowed access types.
ACCESS_SYSTEM_SECURITY = 0x01000000
MAXIMUM_ALLOWED = 0x02000000
The generic rights.
GENERIC_ALL = 0x10000000
GENERIC_EXECUTE = 0x20000000
GENERIC_WRITE = 0x40000000
GENERIC_READ = 0x80000000
The object ACE flags (32-bit).
ACE_OBJECT_TYPE_PRESENT = 1
ACE_INHERITED_OBJECT_TYPE_PRESENT = 2
ACL_CONSTANTS
Current revision.
ACL_REVISION = 2
ACL_REVISION_DS = 4
History of revisions.
ACL_REVISION1 = 1
MIN_ACL_REVISION = 2
ACL_REVISION2 = 2
ACL_REVISION3 = 3
ACL_REVISION4 = 4
MAX_ACL_REVISION = 4
Absolute security descriptor. Does not contain the owner and group SIDs, nor
the sacl and dacl ACLs inside the security descriptor. Instead, it contains
pointers to these structures in memory. Obviously, absolute security
descriptors are only useful for in memory representations of security
descriptors. On disk, a self-relative security descriptor is used.
Attribute: Security descriptor (0x50). A standard self-relative security
descriptor.
NOTE: Always resident.
NOTE: Not used in NTFS 3.0+, as security descriptors are stored centrally
in FILE_$Secure and the correct descriptor is found using the security_id
from the standard information attribute.
On NTFS 3.0+, all security descriptors are stored in FILE_$Secure. Only one
referenced instance of each unique security descriptor is stored.
FILE_$Secure contains no unnamed data attribute, i.e. it has zero length. It
does, however, contain two indexes ($SDH and $SII) as well as a named data
stream ($SDS).
Every unique security descriptor is assigned a unique security identifier
(security_id, not to be confused with a SID). The security_id is unique for
the NTFS volume and is used as an index into the $SII index, which maps
security_ids to the security descriptor's storage location within the $SDS
data attribute. The $SII index is sorted by ascending security_id.
A simple hash is computed from each security descriptor. This hash is used
as an index into the $SDH index, which maps security descriptor hashes to
the security descriptor's storage location within the $SDS data attribute.
The $SDH index is sorted by security descriptor hash and is stored in a B+
tree. When searching $SDH (with the intent of determining whether or not a
new security descriptor is already present in the $SDS data stream), if a
matching hash is found, but the security descriptors do not match, the
search in the $SDH index is continued, searching for a next matching hash.
When a precise match is found, the security_id coresponding to the security
descriptor in the $SDS attribute is read from the found $SDH index entry and
is stored in the $STANDARD_INFORMATION attribute of the file/directory to
which the security descriptor is being applied. The $STANDARD_INFORMATION
attribute is present in all base mft records (i.e. in all files and
directories).
If a match is not found, the security descriptor is assigned a new unique
security_id and is added to the $SDS data attribute. Then, entries
referencing the this security descriptor in the $SDS data attribute are
added to the $SDH and $SII indexes.
Note: Entries are never deleted from FILE_$Secure, even if nothing
references an entry any more.
The $SDS data stream contains the security descriptors, aligned on 16-byte
boundaries, sorted by security_id in a B+ tree. Security descriptors cannot
cross 256kib boundaries (this restriction is imposed by the Windows cache
manager). Each security descriptor is contained in a SDS_ENTRY structure.
Also, each security descriptor is stored twice in the $SDS stream with a
fixed offset of 0x40000 bytes (256kib, the Windows cache manager's max size)
between them; i.e. if a SDS_ENTRY specifies an offset of 0x51d0, then the
the first copy of the security descriptor will be at offset 0x51d0 in the
$SDS data stream and the second copy will be at offset 0x451d0.
$SII index. The collation type is COLLATION_NTOFS_ULONG.
$SDH index. The collation rule is COLLATION_NTOFS_SECURITY_HASH.