Home | Files | Attributes | Concepts | Glossary

# Attribute - $SECURITY_DESCRIPTOR (0x50)

Previous Next

## Overview

    Standard Attribute Header?

The security descriptor can be summarised as:

- A header (may be flags), followed by one or two ACLs and two SIDs.
- The first ACL contains auditing information and may be absent.
- The second ACL contains permissions (who can do what).
- Each ACL contains one or many ACEs.
- Each ACE contains a SID.
- The last two SIDs show the owner of the object (User and Group)

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:

- The owner of the file
- Permissions the owner has granted to other users
- What actions should be logged (auditing)

## Layout of the Attribute

## Notes

### Size

As defined in $AttrDef, this attribute has a no minimum or maximum size.

### Other Information

## Layout of the stream

## Questions

- How are the ACEs of directories inherited?
- How can we fit the ACEs into a normal looking Unix file system?
- How can we tie the file permissions into PAM or SMB?
- Can we use NT authentication, somehow?

## To Do

- Decide which Standard, and Specific, Rights relate to which filesystem activities, e.g. FILE_APPEND_DATA will allow a user to extend a file, but not create one.
- Experiment to see if the zeros we see are padding and that the flag-like fields are flags.
- Experiment with the Generic Read / Write / Execute / All flags.

### Header

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

## 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.

### ACE

Offset | Size | Description
--- | --- | ---
0x00 | 1 | Type
0x01 | 1 | Flags
0x02 | 2 | Size
0x04 | 4 | Access mask
0x08 | V | SID

### Flags

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

## Access Mask / Access Rights

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

## SID (Security Identifier)

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.

### Security Descriptor Control Flags

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

### OWNER DEFAULTED

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.

### GROUP DEFAULTED

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.

### DACL PRESENT

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.

### DACL DEFAULTED

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.

### SACL PRESENT

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.

### SACL DEFAULTED

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.

### SELF RELATIVE

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.

Copyright (C) Validate HTML Validate CSS