Skip to main content

Parse SDDL strings

Project description

Install

pip3 install sddl-parser

Usage

Parse an SDDL string

>> from sddl_parser import parse_sddl
>> sddl = "O:SYG:SYD:AI(A;ID;GA;;;SY)"
>> parse_sddl(sddl)
SDDL(
    owner=<SIDEnum.LOCAL_SYSTEM: 'S-1-5-18'>,
    group=<SIDEnum.LOCAL_SYSTEM: 'S-1-5-18'>,
    dacl=ACL(
        flags={<SDDLFlags.SDDL_AUTO_INHERITED: 2>},
        aces=[
            ACE(type=<AceType.ACCESS_ALLOWED: 0>,
                flags={<AceFlags.INHERITED: 16>},
                object_guid='',
                rights_int=268435456,
                inherit_object_guid='',
                sid=<SIDEnum.LOCAL_SYSTEM: 'S-1-5-18'>,
                conditional_ace_string=None,
                conditional_ace=None,
                rights={<GenericAccessRights.GENERIC_ALL: 268435456>}
            )
        ]),
    sacl=None
)

Parse an ACE

>> from sddl_parser import parse_ace
>> ace = "(A;ID;0x10030;;;AC)"
>> parse_ace(ace)
ACE(type=<AceType.ACCESS_ALLOWED: 0>,
    flags={<AceFlags.INHERITED: 16>},
    object_guid='',
    rights_int=65584,
    inherit_object_guid='',
    sid=<SIDEnum.ALL_APP_PACKAGES: 'S-1-15-2-1'>,
    conditional_ace_string=None,
    conditional_ace=None,
    rights={
        <GenericAccessRights.READ_PROPERTY: 16>,
        <GenericAccessRights.WRITE_PROPERTY: 32>,
        <GenericAccessRights.STANDARD_DELETE: 65536>
    }
)

See that GenericAccessRights.ACCESS4 is returned. That's an indication that the SDDL type should be specified. To get more accurate rights, use .as_type() on the object or pass the Rights object to the parse_ace function

>> from sddl_parser import parse_ace, FileAccessRights
>> ace = "(A;ID;0x1200a9;;;AC)"
>> # alternatively, run parse_ace(ace, FileAccessRights)
>> parse_ace(ace).as_type(FileAccessRights)
ACE(type=<AceType.ACCESS_ALLOWED: 0>,
    flags={<AceFlags.INHERITED: 16>},
    object_guid='',
    rights_int=1179817,
    inherit_object_guid='',
    sid=<SIDEnum.ALL_APP_PACKAGES: 'S-1-15-2-1'>,
    conditional_ace_string=None,
    conditional_ace=None,
    rights={
        <FileAccessRights.FILE_READ_DATA: 1>,
        <FileAccessRights.FILE_READ_EA: 8>,
        <FileAccessRights.FILE_EXECUTE: 32>,
        <FileAccessRights.FILE_READ_ATTRIBUTES: 128>,
        <FileAccessRights.READ_CONTROL: 131072>,
        <FileAccessRights.SYNCHRONIZE: 1048576>,
        <FileAccessRights.FILE_GENERIC_READ: 1179785>,
        <FileAccessRights.FILE_GENERIC_EXECUTE: 1179808>
    }
)

All rights are IntEnums, so if you want to check for generic rights, FileAccessRights.DELETE is equivalent to GenericAccessRights.DELETE

If you want to map SIDs to strings, you can pass in sidmap:

>>> from sddl_parser import api
>>> test = "O:S-1-20-20-20G:SYD:"
>>> sidmap = {"S-1-20-20-20": "DOMAIN\\user"}
>>> api.parse_sddl(test, sidmap=sidmap)
SDDL(
    owner="DOMAIN\\user",
    group=SIDEnum.LOCAL_SYSTEM,
    dacl=ACL(flags={SDDLFlags.NO_ACCESS_CONTROL}, aces=[]),
    sacl=None,
)

Conditional ACE

From MS docs:

A Conditional ACE allows a conditional expression to be evaluated when an access check

The sddl_parser library will return the conditional ACE string as well as a custom intermediate language representation of the conditional ACE. It's not the prettiest IL. I'm open to suggestions.

The ABNF definition for conditional ACEs is defined in [MS-DYP] - 2.5.1.1.

>>> from pprint import pprint
>>> test = '(XA;ID;0x1200a9;;;BU;(WIN://SYSAPPID Contains "MICROSOFT.MICROSOFTEDGE.STABLE_ABC123"))'
>>> parse_ace(test)
ACE(type=<AceType.ACCESS_ALLOWED_CALLBACK: 9>,
    flags={<AceFlags.INHERITED: 16>},
    object_guid='',
    rights_int=1179817,
    inherit_object_guid='',
    sid=<SIDEnum.BUILTIN_USERS: 'S-1-5-32-545'>,
    conditional_ace_string='(WIN://SYSAPPID Contains "MICROSOFT.MICROSOFTEDGE.STABLE_ABC123")',
    conditional_ace=[
        ('ATTRNAME', 'WIN://SYSAPPID'),
        ('OPERATION', 'Contains'),
        ('VALUE', 'MICROSOFT.MICROSOFTEDGE.STABLE_ABC123')
    ],
    rights={
        <GenericAccessRights.CREATE_CHILD: 1>,
        <GenericAccessRights.SELF_WRITE: 8>,
        <GenericAccessRights.WRITE_PROPERTY: 32>,
        <GenericAccessRights.LIST_OBJECT: 128>,
        <GenericAccessRights.READ_CONTROL: 131072>,
        <GenericAccessRights.SYNCHRONIZE: 1048576>
    }
)
>>> test = '(XA;ID;0x1200a9;;;BU;(@User.Title=="PM" && (@User.Division=="Finance" || @User.Division == "Sales")))'
>>> parse_ace(test)
ACE(type=<AceType.ACCESS_ALLOWED_CALLBACK: 9>,
    flags={<AceFlags.INHERITED: 16>},
    object_guid='',
    rights_int=1179817,
    inherit_object_guid='',
    sid=<SIDEnum.BUILTIN_USERS: 'S-1-5-32-545'>,
    conditional_ace_string='(@User.Title=="PM" && (@User.Division=="Finance" || @User.Division == "Sales")',
    conditional_ace={
        'TYPE': 'AND',
        'VALUES': [
            [('ATTRNAME', '@user.Title'), ('OPERATION', '=='), ('VALUE', 'PM')],
            {
                'TYPE': 'GROUP', 'VALUE': {
                    'TYPE': 'OR',
                    'VALUES': [
                        [('ATTRNAME', '@user.Division'), ('OPERATION', '=='), ('VALUE', 'Finance')],
                        [('ATTRNAME', '@user.Division'), ('OPERATION', '=='), ('VALUE', 'Sales')]
                    ]
                }
            }
        ]
    },
    rights={
        <GenericAccessRights.CREATE_CHILD: 1>,
        <GenericAccessRights.SELF_WRITE: 8>,
        <GenericAccessRights.WRITE_PROPERTY: 32>,
        <GenericAccessRights.LIST_OBJECT: 128>,
        <GenericAccessRights.READ_CONTROL: 131072>,
        <GenericAccessRights.SYNCHRONIZE: 1048576>
    }
)

Access Rights Available

All right enums are given here

>> from sddl_parser import rights_enums
>> for x in dir(rights_enums):
>>   print(i)
AlpcAccessRights
AuditAccessRights
DebugAccessRights
DesktopAccessRights
DirectoryAccessRights
DirectoryServiceAccessRights
EnlistmentAccessRights
EventAccessRights
FileAccessRights
FileDirectoryAccessRights
FilterConnectionPortAccessRights
FirewallAccessRights
FirewallFilterAccessRights
GenericAccessRights
IoCompletionAccessRights
JobAccessRights
KeyAccessRights
LsaAccountAccessRights
LsaPolicyAccessRights
LsaSecretAccessRights
LsaTrustedDomainAccessRights
MemoryPartitionAccessRights
MutantAccessRights
PrintSpoolerAccessRights
ProcessAccessRights
RegistryKeyAccessRights
RegistryTransactionAccessRights
ResourceManagerAccessRights
SamAliasAccessRights
SamDomainAccessRights
SamGroupAccessRights
SamServerAccessRights
SamUserAccessRights
SemaphoreAccessRights
ServiceAccessRights
ServiceControlManagerAccessRights
SessionAccessRights
SymbolicLinkAccessRights
ThreadAccessRights
TimerAccessRights
TokenAccessRights
TraceAccessRights
TransactionAccessRights
TransactionManagerAccessRights
WindowStationAccessRights
WnfAccessRights

Shoulders of Giants

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sddl_parser-0.6.2.tar.gz (16.9 kB view details)

Uploaded Source

Built Distribution

sddl_parser-0.6.2-py3-none-any.whl (18.1 kB view details)

Uploaded Python 3

File details

Details for the file sddl_parser-0.6.2.tar.gz.

File metadata

  • Download URL: sddl_parser-0.6.2.tar.gz
  • Upload date:
  • Size: 16.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.2 CPython/3.11.8 Linux/6.5.0-1016-azure

File hashes

Hashes for sddl_parser-0.6.2.tar.gz
Algorithm Hash digest
SHA256 3eed72cc8df5a9ef6635157a68550a56659a79d4c4c2e6562f43a46fb0b61976
MD5 e1f900d7f8367f587ceb781cf4dd6732
BLAKE2b-256 6696b969905e6af1de3fcbd4cb44b2ac7c298e372fce3f6493c4436a02b067ec

See more details on using hashes here.

File details

Details for the file sddl_parser-0.6.2-py3-none-any.whl.

File metadata

  • Download URL: sddl_parser-0.6.2-py3-none-any.whl
  • Upload date:
  • Size: 18.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.2 CPython/3.11.8 Linux/6.5.0-1016-azure

File hashes

Hashes for sddl_parser-0.6.2-py3-none-any.whl
Algorithm Hash digest
SHA256 a931b2d22b4925f5eafa9c35d7810f498a25dc25b94b6f41c5c61e2dda91c2cb
MD5 79dc2db4419fbb2ed260bdd2fbf650d0
BLAKE2b-256 545552c50259caf4c54409ef58f7facc99d37a26282410efdc0afae5885c96ca

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page