There is no need to talk about the critical role Active Directory plays within the organization. Securing Active Directory is a massive part of the overall organization security, configuration, and permission and Access Control List (ACL).

Reading Active directory ACL is considered a simple task, but understanding it and finding possible weak permission is challenging. Once you finish reading this post, you will learn to create an Active Directory ACL report and read it easily using an automated PowerShell Module ADSecurityReporter.

Downloading the Active Directory ACL Reporter

If you are in a rush and want to just download and use the script, feel free and download the ADSecurity Reporter PowerShell Module from PowerShellGallery.com Also, you can help in making the code better or report issues by contributing to my Github repo from here.

New features will be added to this module, So make sure to star the GitHub repo or make sure you always have the latest version.

Known Issue: Not compatible with PowerShell7 and Active Directory Module build 0. You can check the module version by running the following cmdlet

(get-module activedirectory).Version.Build

This is because the ActiveDirectory Module won’t load its AD: PSDrive in PS7.

If you want to use PowerShell 7, then you need Windows Server 2019, as it comes with an updated Module with build 1

Versions and Updates Progress: 5/Oct/2022

Version 1.3 Update:

  • Added GenerateCSVPath parameter to generate CSV report.
  • The GenerateHTMLPath is no longer a mandatory parameter, and you can skip it.
  • If none of GenerateCSVPath or GenerateHTMLPath are used, then the script returns the result through the pipeline.
  • Minor fixes.

Minor Fixes

Prerequisites

ADSecurityReporter requires Windows ActiveDirectory PowerShell module installed. Also, use the highest privilege to run this script to get accurate results.

The ADSecurityReporter tested on a Domain Controller running Windows Server 2012 R2 and on another Domain Controller running Windows Server 2019.

For this tutorial, I used a test domain named Test.local.

If you are looking to know the details of how this script work and how the Get-ACL find the information, read my post on Microsoft PowerShell Community DevBlog, Understanding Get-ACL and AD Drive Output

Issues with Active Directory ACL, Get-ACL, and ObjectType GUID

When getting the ACL in Active Directory by running the PowerShell cmdlet such as (Get-Acl 'AD:OU=PC,DC=Test,DC=local').access the result may look like this.

ActiveDirectoryRights : ReadProperty, WriteProperty, ExtendedRight
InheritanceType       : All
ObjectType            : 91e647de-d96f-4b70-9557-d63ff4f3ccd8
InheritedObjectType   : 00000000-0000-0000-0000-000000000000
ObjectFlags           : ObjectAceTypePresent
AccessControlType     : Allow
IdentityReference     : BUILTIN\Administrators
IsInherited           : True
InheritanceFlags      : ContainerInherit
PropagationFlags      : None

In a quick look, you can understand that the BUILTIN\Administrators group has Allow to the object type 91e647de-d96f-4b70-9557-d63ff4f3ccd8, and the allowed permissions are: Read, Write, and Extended rights. Such results cause more confusion. So which object exactly does the group have access to? and what is ExtendedRight? To make things a bit more complex, check this case

ActiveDirectoryRights : ExtendedRight
InheritanceType       : None
ObjectType            : 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2
InheritedObjectType   : 00000000-0000-0000-0000-000000000000
ObjectFlags           : ObjectAceTypePresent
AccessControlType     : Allow
IdentityReference     : S-1-5-21-777821053-113225789-598796665-1158
IsInherited           : False
InheritanceFlags      : None
PropagationFlags      : None

A SID account has the Allow access to an ExtendedRight. Now, what are these extended rights? The extended rights are represented by the ObjectType GUID.

What ADSecurityReporter does

The ADSecurityReporter PowerShell Script Module is an Active Directory ACL scanner that goes through Active Directory ACL, starting from the top-level domain and through all OU and containers with many customization options. get a list of all ADObject with their assigned permission, and present it in a formatted HTML report or to the console.

The ADSecurityReporter support excluding option to make the report show what you are looking for. So you can exclude CreatorOwner, NTAuthority, Builtin, Everyone, and/or Domain groups account from the report.

The ADSecurityReporter comes to resolve the ACL in Active Directory readability issues and what permission they have on which object. Also, the ADSecurityReporter script resolves ObjectType to a readable output to give more accurate results.

Using the ADSecurityReporter Module cmdlets.

The ADSecurityReporter has three supported cmdlets:

  • Get-PscActiveDirectoryACL: This cmdlet is meant to get the ACL for the Active Directory.
  • Convert-PscGUIDToName: This cmdlet convert the Active Directory ACL ObjectType GUID to name.

Scanning Domain Root ACL using Get-PscActiveDirectoryACL cmdlet

Let’s start with the Get-PscActiveDirectoryACL cmdlet and scan the Test.local domain, and check the domain ACL security. The supported parameters are:

  • DontRunBasicSecurityCheck: Bypass a basic security check which tries to detect if there is any hidden AD Object. [Switch]
  • GenerateHTMLPath: Generate HTML report.[string]
  • GenerateCSVPath: Generate CSV report.[string]
  • [Mandatory]ACLToInclude: Define the scanning scope which include [ValidateSet]
    • All: Scan the entire Active Directory tree.
    • TopLevelDomainOnly: Scan the root domain controller only.
    • OUScanOnly: Scan all OU and Containers without scanning the Top Level Domain.
  • ScanDNName: Scan a part of Active Directory, for example, an OU Tree. The path should be distinguished by name format.
  • ExcludeNTAUTHORITY: Exclude NTAuthority from the results.[switch]
  • ExcludeInheritedPermission: Exclude Inherited permission and show only explicit assigned permissions.
  • ExcludeBuiltIN: Exclude Builtin accounts such as Administrators from the results.[switch]
  • ExcludeCreatorOwner: Exclude CreatorOwner from the results.[switch]
  • ExcludeEveryOne: Exclude the Everyone group from the results.[switch]
  • ExcludeGroups: Exclude Active Directory groups from the results.[switch]

You can use the parameter above to have a report that fits your need with the minimum amount of unwanted data.

Its highly recommend to review all Active Directory ACL and review group membership too, also avoid giving users permission they dont need.

Using the Get-PscActiveDirectoryACL

So let try the Get-PscActiveDirectoryACL and play with the supported parameters, then see what the results look like.

Using the ACLToInclude parameter support three arguments, TopLevelDomain, OUScan and All

Get-PscActiveDirectoryACL -ACLToInclude All
Get-PscActiveDirectoryACL cmdlet
Get-PscActiveDirectoryACL cmdlet

Remember the ExtendedRights issue and how it was referred to using a GUID. Now you know what ExtendedRights refers to, and it translated to Advance Permission ==> Permission Name

The Rights column shows what right the AD Object has and to which exact attribute.

You can use the ScanDNName parameter to scan a specific OU tree, but make sure to use DN format

Get-PscActiveDirectoryACL -ScanDNName 'OU=FM Users,DC=Test,DC=local'

Generating HTML Report

By using the GenerateHTMLPath you can generate the same output but in a nice formatted HTML report. you need to use the GenerateHTMLPath parameter with the path to store the file.

Get-PscActiveDirectoryACL -ACLToInclude all -GenerateHTMLPath C:\MyReprot.html

Once you execute the code above, the script generates a report and stores it in the specified path. The report looks like the following.

Active Directory ACL for the root domain.
Active Directory ACL for the root domain.
Related Post: Learn how to Change AD Connect Sync Account Password.

Using The Get-PscActiveDirectoryACL Parameters to Find a Possible Active Directory Compromise.

The Get-PscActiveDirectoryACL report can be long, and there might be a lot of unwanted noise. To simplify it, let’s get a report which excludes the CreatorOwner, Everyone, Groups, Built-in Accounts, and the NTAutority accounts.

This will exclude all accounts and only keep the AD user account.

Get-PscActiveDirectoryACL -ACLToInclude TopLevelDomainOnly -ExcludeNTAUTHORITY -ExcludeBuiltIN -ExcludeCreatorOwner -ExcludeEveryOne -ExcludeGroups

The result looks like the following.

Using the Get-PscActiveDirectoryACL to Get Active Directory ACL Top Level domain
Using the Get-PscActiveDirectoryACL to Get Active Directory ACL Top Level domain

There is a SID account that has DS-Replication-Get-Change and DS-Replication-Get-Change-All. These results are not a good thing. There might be an attacker replicating the Active Directory Database to get a Golden Ticket.

Finding Hidden Active Directory Account.

The ADSecurityReporter supports a basic method to check if there is a hidden active directory account in your domain. A hidden AD user account is not visible, not even to the Domain Admin. The hidden account can be a member of the Domain Admins group. Still, no one can see it.

One of the methods used to hide an Active Directory account is by denying Enterprise Admins access to a certain OU or container by changing the OU or container ACL.

The Get-PscActiveDirectoryACL cmdlet scans your Active Directory and tries to find objects with Objectclass is $Null, and if it finds one, the script shows a warning with the suspicious location to check.

In the screenshot below there is a suspicious account hidden in the BadContainer AD container. So you can check that location and make sure you have the Allow rights to list the CN or OU content.

Possible hidden account in AD
Possible hidden account in AD

Using Convert-PscGUIDToName cmdlet

The Convert-PscGUIDToName cmdlet helps in converting Active Directory ACL ObjectType and InheritedObjectType from a GUID to a name. For example, the following Active Directory ACE entry has two GUID.

ActiveDirectoryRights : ExtendedRight
InheritanceType       : All
ObjectType            : ab721a53-1e2f-11d0-9819-00aa0040529b
InheritedObjectType   : bf967aba-0de6-11d0-a285-00aa003049e2
ObjectFlags           : ObjectAceTypePresent, InheritedObjectAceTypePresent
AccessControlType     : Allow
IdentityReference     : TEST\Exchange Windows Permissions
IsInherited           : False
InheritanceFlags      : ContainerInherit
PropagationFlags      : None

Using the Convert-PscGUIDToName helps in getting these GUID names.

Convert-PscGUIDToName -GUID2Name ab721a53-1e2f-11d0-9819-00aa0040529b
User-Change-Password
Convert-PscGUIDToName -GUID2Name bf967aba-0de6-11d0-a285-00aa003049e2
User
Convert-PscGUIDToName

Also running the Convert-PscGUIDToName cmdlet alone gets a list of all available ObjectType

Convert-PscGUIDToName All GUID
Convert-PscGUIDToName All GUID

Conclusion

I hope this script can help you map and have a proper Active Directory ACL report and add a small security benefit to your organization. Feel free to contact me or comment here if you have any issues or questions.

Did you know that I have a Facebook group, join me

5/5 - (7 votes)