It's no secret that Microsoft tends to do goofy things sometimes, and seemingly do things just for the sake of doing them. When it comes to security descriptors, SDDL (Security Descriptor Definition Language) seems to be one of those cases.
At the very lowest level of the operating system, pretty much any security descriptor whether it's a file ACL, registry ACL, or anything else that defines the security attributes of an object is referred to by a compact binary representation of all the security associated with an object. For the most part, Microsoft gives us a nice way of visualizing and representing this kind of data.
For example, we can either open up the GUI security properties of an object, or use something like cacls.exe or the powershell cmdlet Get-Acl to get a mostly nicely formatted list of security ACLs:
PS C:\Users\lkwiecinski> Get-Acl testfile.txt | fl
Path : Microsoft.PowerShell.Core\FileSystem::C:\Users\lkwiecinski\testfile.tx
t
Owner : BUILTIN\Administrators
Group : DOMAIN-TEST\Domain Users
Access : NT AUTHORITY\SYSTEM Allow FullControl
BUILTIN\Administrators Allow FullControl
DOMAIN-TEST\LKwiecinski Allow FullControl
As you can see, we get a nice representation of this security descriptor, instead of having to learn to read assembly and binary (although if you want to learn more about how the OS handles security descriptors: knock yourself out).
However, there is yet another way to display security descriptors that is slightly in between. It's about as readable as the regular expression for e-mail address validation at first glance. This method is called SDDL.
In the above Get-Acl outout, I purposefully cut it off a bit. At the very end of Get-Acl's output is the actual SDDL line for the file. The SDDL output looks like this:
Sddl : O:BAG:DUD:(A;ID;FA;;;SY)(A;ID;FA;;;BA)(A;ID;FA;;;S-1-5-21-131149751-17
69473516-1629300891-114223)
Not exactly very user friendly, is it? For the most part, you'll never have to look at, or use SDDL, but what if, for example, you need to modify the registry to allow a non-Domain Admin user account to query the Security Event Log? Whether your monitoring system requires it, your SIEM needs to query your Event Logs, or you want to run Cisco Content Directory Agent, the ACLs for the Event Log are stored in the registry...and they are stored in SDDL.
Since we know the ACL for this testfile.txt, we can look at the SDDL and try to break it apart and see if we can learn to understand it a little bit better.
SDDL is composed of four parts. The Owner of the object, the Primary Group of the object, the actual ACLs themselves, and optional SACL Entries.
Microsoft was very careful to craft SDDL in such a way that these random letters don't interfere with each other. It's kind of like Morse Code in this way, where even though you're limited to just dots and dashes, you can form any letter, and have any letter follow any letter without confusion.
Enough talking, let's color code and break down this SDDL string:
O:BAG:DUD:(A;ID;FA;;;SY)(A;ID;FA;;;BA)(A;ID;FA;;;S-1-5-21-131149751-17
69473516-1629300891-114223)
Let's also remind ourselves of the "nice" output:
Owner : BUILTIN\Administrators
Group : DOMAIN-TEST\Domain Users
Access : NT AUTHORITY\SYSTEM Allow FullControl
BUILTIN\Administrators Allow FullControl
DOMAIN-TEST\LKwiecinski Allow FullControl
O: stands for owner, and the owner in this case is BA. BA stands for Built in Administrators, as we see in the nice output above.
G: defines our group, and in this case the group is DU. DU stands for Domain Users.
D: starts our actual ACLs, which are in themselves a 5 part affair.
Let's take one as an example: (A;ID;FA;;;SY)
Microsoft defines the DACL as follows:
(ace_type;ace_flags;rights;object_guid;inherit_object_guid;account_sid;(resource attribute)).
As you can see in the example above, some of these fields are allowed to be blank. Our example string has the following set:
ace_type=A
ace_flags=ID
rights=FA
account_sid=SY
As you can also see, the SID doesn't HAVE to be an actual SID, but can be one of the pre-defined constants. This particular DACL refers to the "NT AUTHORITY\SYSTEM ALLOW FULL ACCESS" entry in the ACL.
So we can see that A stands for Allow, FA probably stands for Full Access, and SY probably stands for System (See, sometimes Microsoft makes sense after all). The ID stands for "Inherited", but it's not as important as the other entries.
All of these flags and built in constants can be found HERE and the SID shortcuts can be found at this link
Let's take a look at an entry we will add. Let's say I have a user called cdawmiadmin in my domain, and I add that user to the file's ACL to give it READ rights. If I re-run Get-Acl, I will have a new SDDL string:
Sddl : O:BAG:DUD:AI(A;;FR;;;S-1-5-21-131149751-1769473516-1629300891-118901)(
A;ID;FA;;;SY)(A;ID;FA;;;BA)(A;ID;FA;;;S-1-5-21-131149751-1769473516-16
29300891-114223)
We see two things have changed. We have an additional entry: (A;;FR;;;S-1-5-21-131149751-1769473516-1629300891-118901) and we also have a slight change to our DACL with it now having an "AI" in front of the parenthesized entries. The new entry of AI is explained on this MSDN page and basically says that there are things that are auto inherited. However let's look at the actual ACL for our new addition and see if we can make sense of it.
First, let's get the SID of our cdawmiadmin user so we're clear on what we have here:
C:\Users\lkwiecinski>wmic useraccount where name="cdawmiadmin" get name,sid
Name SID
cdawmiadmin S-1-5-21-131149751-1769473516-1629300891-118901
Yep, our SIDs match, we're all good to go. If we were not sure, we could always do the operation the other way and do some powershell action:
$objSID = New-Object System.Security.Principal.SecurityIdentifier `
("ENTER-SID-HERE")
$objUser = $objSID.Translate( [System.Security.Principal.NTAccount])
$objUser.Value
Anyway, let's look at our SDDL and break it down.
ace_type=A - so it means we are granting access
ace_flag= empty... since this time it is not an inherited permission
rights=FR - which means File Read according to our handy MSDN guide
object_guid is empty
inherit_object_guid is empty
account_sid=the SID of our cdawmiadmin user.
Hopefully reading through this helps you to understand how to read SDDL a bit better, since it's not ACTUALLY as cryptic as it seems. Knowing how to read it will allow you to write your own SDDL entries for things like the CustomSD attribute of the Event Log.
There is one more caveat though: Microsoft also accepts HEX flags as the rights portion of the SDDL. So instead of having FR for file read, or FA for full access, you might see something like 0xf0007 instead. Unfortunately, Microsoft does not give us a handy guide in deciphering these hex versions. When writing SDDL, use the string versions, and since only Microsoft sets them in hex, we don't really have to worry about them.
Labels: SDDL, security, Windows