Forensics: Active Directory ACL investigation


A Couple of Sensitive Spots

Active Directory are full of delegated rights and permissions that grant privileges to security principals (User, Group Managed Service Account, Group and Computer Objects). Some permissions are more sensitive than others and should be kept only for privileged accounts such as for Tier 0 administrators (Read about the credential tier model and Securing Privileged Access here https://technet.microsoft.com/en-us/library/mt631194.aspx ) or equivalent. Which are these sensitive object in Active Directory? Well it depends on how your structure are designed and where you store your sensitive objects, but there are a couple of standard objects you should look at.

These are examples of locations to keep a good control of the Access Control Lists (ACL) on:

  • Domain Partition Node
  • Configuration Partition Node
  • Schema Partion Node
  • AdminSDHolder
  • DefaultSecurityDescriptors on objectClasses in the Schema Partition

Security issues

What kind of risks should we be looking for?

Attackers that try to maintain long-term persistence

If an attacker once gain high privileges, like let's say Domain Admin access, this individual would probably like to keep a backdoor open even after you thought you had removed the foothold for good. To do so the attacker could potentially adding a couple of access control entries for a rouge account and by doing so the attacker could regain all privileges when the attacker chooses to.

Applications/Service accounts delegated too much privilege

Often are service accounts granted privileges in Active Directory. It's crucial these permissions are delegated with the Principle of Least Privilege (PoLP) since these service accounts are usually a security issue already with it's exposure and it's probably never changed and maybe even known password. If someone would get hold of a service account it could be used to elevate privileges, steal credentials or even steal secrets from Active Directory.

Escalation of Privileges

During the lifetime of an AD there has probably been a lot of projects or applications that had requirements on who and what should been delegated permissions. There's a big chance that some of these AD delegations are not valid anymore and people has left their function or even the company, but still the delegated permissions have remained. This could potentially let a user to maintain high privileges or even do escalation of privileges.

How to spot the difference

If you ever have been browsing objects in Active Directory for permissions you know it could be quite hard to get a good overview, but there are some help to get. AD ACL Scanner is a PowerShell script that produce reports of access control lists (ACL) in Active Directory that would simplify the process of analyzing permissions. See this previous blog http://blogs.technet.com/b/pfesweplat/archive/2013/05/13/permissions-in-ad-lost-control.aspx.

What kind of permissions are more of a risk than others?

Here's a couple of permissions that you should watch out for (This is not a compete list):

  • Full Control on all objects
  • Create Child Objects
    • Create new user accounts, groups etc.
    • Create dynamic objects, objects with a Time-To-Live and will disappear when TTL is meet.
  • All Extended Rights
    • Password Resets
    • Replicating Directory Changes All
    • Potential access to all confidential attributes.
  • Extended Right: Replicating Directory Changes All
    • This extended rights should ONLY be delegated to services that do password synchronization like the Azure AD Connect tool  or other services using DSgetNCChanges for password sync.
    • FIM/MIM does not need this permissions see: https://support.microsoft.com/en-us/kb/303972
  • Reset Passwords
  • Write Property to objects or sensitive attributes
    • Modify group memberships.
    • Write userPrinicpalName.
    • Write altSecIdentities
    • Write userCertificate
    • Write userAccountControl.
    • Write servicePrincipalName.
  • Write Public Information
    • Includes userPrincipalName.
  • Write Membership
    • Includes member and memberOf.
  • Write User Account Restrictions
    • Includes userAccountControl.
  • Write userPrincipalName
    • Access to modify the userPrincipalName could let someone with a valid smart card to logon as someone else by having the SubjAltName field of the smart to match another Active Directory user account.
  • Write userAccountControl
    • Allow blank password.
    • Downgrade Kerberos to DES only.
    • Enable/Disable accounts.
    • Store password using reversible encryption.
  • Write msDS-SupportedEncryptionTypes
    • Downgrade Kerberos encryption.
  • Write Permissions
    • Replace current permissions with new more relaxed or granting access to a malicious account.
  • Write servicePrincipalName
    • By adding a service principal name to an account an attacker  could potentially request a Kerberos TGS for the account and save the TGS to a file and perform offline TGS password cracking as long as RC4 Kerberos encryption is allowed.
  • Take Ownership
    • Take owner ship and then replace current permissions with new more relaxed or granting access to a malicious account.
  • Link Group Policy Object
    • Introduce new settings that would grant access or apply malicious code on the operating systems.

Compare the top nodes of each AD partition with the defaults

By comparing the top node of the Domain, Configuration, AdminSDHolder and Schema partition with the defaults it will make it much easier to identify permissions that are anomalous or suspicious.

So how can we differ the custom settings from the defaults?

With AD ACL Scanner you can run a comparison with a previous created CSV file (If you got one saved from when the domain was fresh 🙂 ) or download a template with AD ACL Scanner for default DACLs (discretionary access control list) for the version of domain controllers you are running

1. Run the script and press Connect to connect to your domain.

2. Select Enable Compare.

Fig. 1 Compare and download template

Fig. 1 Compare and download template

3. Download "Each NC root combined" for you highest version of operating system of your DC's and click Close.

Fig. 2. Download Links

Fig. 2. Download Links

4. Click Select Template and select the downloaded csv file. For example: Win_2012_R2_Default_DACL_NC.csv.

5. Select Use nodes from template to let the template decided where to scan.

6. Select View Owner in View in report on the Scan Options tab to include the ownership of each node.

7. Click Run Scan.

Fig. 3. Running a compare report.

Fig. 3. Running a compare report.

8. The results will be presented in a HTLM report, something like this:

Fig. Example report

Fig 4. Example report

Interpreting results

What will the report tell me? The report will show you all the current Access Control Entries and the missing ones.

It will highlight permissions that match (green) the default and missing (red) and new (yellow) permissions from the template.

Fig 5. Understanding the report

Are missing permissions all bad?

If you have missing permissions it much likely it could be that your AD is an upgrade from previous versions of Windows that did not have some of these permissions. But there are permissions added in a pristine AD that will be merged into other Access Control Entries (by the SetEntriesInACL function) at the fist modification of the Access Control List on the domain node by a user or application.

Permission from a pristine domain that are merged into other ACE's.

Fig 6. Permissions that are merged into other ACE's

Fig 6. Permissions that are merged into other ACE's

If these are missing do not panic , its normal! 🙂

What to look for?

New permissions that could lead to control over sensitive objects or systems. If you got applications like Exchange and Lync in your environment you will see a lot of entires added by the domain prep for these application. These permissions are expected and should not be removed, unless you have specific requirements or cleaning up after a removal of the services.

Here's a few examples of permissions that would need an extra attentions.

Full control on the domain level

Full control granted on on domain level is not something you would delegate. The intension were probably to give someone full control on all OU's, but full control on the domain level comes with so much more (like Replicating Directory Changes All) that should stay within Tier 0 admins like Administrators and Domain Admins .

Fig 7. Delegation gone bad.

Fig 7. Delegation gone bad.

Replicating Directory Changes All

This permission should only be delegated to Administrators, Domain Admins and Domain Controllers unless you are using a product that does password sync using hashes, FIM/MIM is not one of them nor SharePoint. FIM/MIM uses agents on DC's for this. AAD Connect is an application that potentially could make use of this right if you are syncing passwords to Azure AD.

Fig 8. Replicate All = Can steal secrets

Fig 8. Replicate All = Can steal secrets

Permissions on AdminSDHolder - Write Member

I would be very suspicious of custom permissions on the AdminSDHolder object (Protection function for protected groups). Any permissions that allow write here could potentially make them self admins at any time without being member of the highly privileged groups.

Fig 9. Add me to Domain Admins at will

Fig 9. Add me to Domain Admins at will

Rouge Owner

As an owner you will have the permissions to modify the ACL on the same object. This gives the owner to grant him/her full controll at any time. Keep an eye for who's owner.

Fig 10. Rogue Owner can change the ACL to suit the situation.

Fig 10. Rogue Owner can change the ACL to suit the situation.

 

Summary

The key here is to know your delegation and your best tool is RBAC! With a good RBAC model following the tier model (Securing Privileged Access ) and using a good naming convenvtion it will be easier to spot bad delegations.

Clean out old stuff too! Remove that old service account that no one uses any more!

Upon this you need to log, monitor and regulary audit your ACL changes.


Comments (13)

  1. turbomcp says:

    awesome stuff
    thanks

  2. hypothesis says:

    The last link in the post includes the dot and is rendered as page error.

    1. Thanks for letting me know. Fixed!

  3. Amer says:

    Amazing work and tool, thanks.

  4. Thanks for this extensive post and the detailed examples.

  5. Ernest Brant says:

    Fantastic article, lots of detailed information with great explanations all in one place (including additional links for further reading); what’s not to like 🙂

  6. Daniel Ulrichs says:

    Nice post.
    For Full Control on the domain level you should also watch out for Enterprise Key Admins, when preparing the domain to 2016 its granted Full Control and is not protected by AdminSDHolder.
    https://secureidentity.se/adprep-bug-in-windows-server-2016/

  7. SCOM-PHL says:

    Keep getting a run time error when clicking on the securing privileged access link in the first paragraph of the article.
    https://technet.microsoft.com/en-us/library/mt631194.aspx.

  8. Reto says:

    It’s a great tool but nomore available.

    I wanted to update from former Version 4.5 but CodePlex is shutting down and I cannot find the actual Version 4.7.2 or even newer.
    Did you place it somwhere else?

  9. Where can I dowload this tool? Codeplex doesn’t work anymore.

  10. I have updated the link to AD ACL Scanner, new url is https://github.com/canix1/ADACLScanner.

    1. Alan says:

      I cannot run the script. Is there something I am missing? Error code – Unrecognized token in source text.
      At C:\scripts\ADACLS\adaclscan.ps1:1188 char:9
      + $code = <<<< @"using System;using System.Drawing;using System.Runtime.InteropServices;namespace System{ public class IconExtractor { public static Icon Extract(string
      file, int number, bool largeIcon) { IntPtr large; IntPtr small; ExtractIconEx(file, number, out large, out small, 1); try { return Icon.FromHandl
      e(largeIcon ? large : small); } catch { return null; } } [DllImport("Shell32.dll", EntryPoint = "ExtractIconExW", CharSet = CharSet.Unicode, Exact
      Spelling = true, CallingConvention = CallingConvention.StdCall)] private static extern int ExtractIconEx(string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmall
      Version, int amountIcons); }}"@
      + CategoryInfo : ParserError: (:) [], ParseException
      + FullyQualifiedErrorId : UnrecognizedToken

Skip to main content