1
votes

I am trying to get effective permissions of certain active directory users on various Active Directory objects. I can see these permissions from the UI - enter image description here

I am trying to get this using Powershell. I have already tried dsacls and Get-Acls but these don't give effective permissions. These both give "who has access/permissions" which is not the same as "who has what effective permissions". These also don't list out all the granular details that would provide context around the effective access.

Any pointers on how this can be achieved programmatically would be really appreciated.

Update -

Effective permissions here would mean which permissions are allowed to the object in reality based on inheritances or other rules set at a different level.

For example -

All the properties in the below example are not visible with Get-ACL. enter image description here

Another example of what Get-Acl shows while the UI tells differently is when I pulled permissions for domain admins on one of the OUs via Get-ACL , after resolving the values in ObjectType and InheritedObjectType (use get-effective access function mentioned by Santiago Squarzon) I get -

enter image description here

While the UI effective access shows-

enter image description here

My end goal is to get all the permission in the above screenshot using powershell.

2
Get-Acl should give you that information. Use the grouping operator (..) to expose that code property. (Get-ACL .\).Access. Can you clarify what you mean by "effective permissions"?Abraham Zinala
All Objects (Full Control) in the ACL you're showing means full control over the ActiveDirectoryRights, it is not the same as Effective Access on Advanced Security Settings. Compare the result of an IdentityReference the you know has full control with the one you're showing, you'll see the difference. In addition, you're not showing if there is other ACL denying Full Control over that IdentityReference. As I said in my answer, you need to know how to read the output of Get-ACL.Santiago Squarzon
This was the only entry for domain controllers. It didn't have any deny rules. I didn't include the identity reference as I wanted to avoid censoring the image. Both the screen shots show the result of the same identity reference.Steve_Greenwood
Just for reference, I edited my answer to show you how Full Control looks like compared with WriteDACL.Santiago Squarzon

2 Answers

1
votes

This is pretty close to what you're looking for. Source for more details. Access Control Lists with Get-ACL are not as easy to read as Effective Access on Advanced Security Settings and I don't think there is a way around that. I do think that, once used to it, Get-ACL gives a lot more details when you know what you're looking for \ filter the ACLs to get what you're looking for.

Code

Function Get-EffectiveAccess {
[CmdletBinding()]
param(
    [Parameter(
        Mandatory,
        ValueFromPipelineByPropertyName
    )]
    [ValidatePattern(
        '(?:(CN=([^,]*)),)?(?:((?:(?:CN|OU)=[^,]+,?)+),)?((?:DC=[^,]+,?)+)$'
    )][string]$DistinguishedName,
    [switch]$IncludeOrphan
)

    begin
    {
        # requires -Modules ActiveDirectory
        $ErrorActionPreference = 'Stop'
        $GUIDMap = @{}
        $domain = Get-ADRootDSE
        $z = '00000000-0000-0000-0000-000000000000'
        $hash = @{
            SearchBase = $domain.schemaNamingContext
            LDAPFilter = '(schemaIDGUID=*)'
            Properties = 'name','schemaIDGUID'
            ErrorAction = 'SilentlyContinue'
        }
        $schemaIDs = Get-ADObject @hash 

        $hash = @{
            SearchBase = "CN=Extended-Rights,$($domain.configurationNamingContext)"
            LDAPFilter = '(objectClass=controlAccessRight)'
            Properties = 'name','rightsGUID'
            ErrorAction = 'SilentlyContinue'
        }
        $extendedRigths = Get-ADObject @hash

        foreach($i in $schemaIDs)
        {
            if(-not $GUIDMap.ContainsKey([System.GUID]$i.schemaIDGUID))
            {
                $GUIDMap.add([System.GUID]$i.schemaIDGUID,$i.name)
            }
        }
        foreach($i in $extendedRigths)
        {
            if(-not $GUIDMap.ContainsKey([System.GUID]$i.rightsGUID))
            {
                $GUIDMap.add([System.GUID]$i.rightsGUID,$i.name)
            }
        }
    }

    process
    {
        $result = [system.collections.generic.list[pscustomobject]]::new()
        $object = Get-ADObject $DistinguishedName
        $acls = (Get-ACL "AD:$object").Access
        
        foreach($acl in $acls)
        {
            
            $objectType = if($acl.ObjectType -eq $z)
            {
                'All Objects (Full Control)'
            }
            else
            {
                $GUIDMap[$acl.ObjectType]
            }

            $inheritedObjType = if($acl.InheritedObjectType -eq $z)
            {
                'Applied to Any Inherited Object'
            }
            else
            {
                $GUIDMap[$acl.InheritedObjectType]
            }

            $result.Add(
                [PSCustomObject]@{
                    Name = $object.Name
                    IdentityReference = $acl.IdentityReference
                    AccessControlType = $acl.AccessControlType
                    ActiveDirectoryRights = $acl.ActiveDirectoryRights
                    ObjectType = $objectType
                    InheritedObjectType = $inheritedObjType
                    InheritanceType = $acl.InheritanceType
                    IsInherited = $acl.IsInherited
            })
        }
        
        if(-not $IncludeOrphan.IsPresent)
        {
            $result | Sort-Object IdentityReference |
            Where-Object {$_.IdentityReference -notmatch 'S-1-*'}
            return
        }

        return $result | Sort-Object IdentityReference
    }
}

Usage

PS \> Get-ADOrganizationalUnit -Filter {Name -eq 'ExampleOU'} | Get-EffectiveAccess | Out-GridView
PS \> Get-EffectiveAccess -DistinguishedName 'OU=ExampleOU,DC=domainName,DC=com' | Out-GridView
PS \> $effectiveAccess = Get-ADGroup exampleGroup | Get-EffectiveAccess -IncludeOrphan
PS \> Get-ADOrganizationalUnit -Filter * | Select -First 10 | Get-EffectiveAccess | Out-GridView

By default, the function will filter all orphaned ACLs. Use the IncludeOrphan switch to include all IdentityReference that begin with S-1-*

Edit

For reference, this is how Full Control looks like with Get-ACL

fullcontrol

Compared with BUILTIN\Administrators which has write permissions on this OU but not Full Control

writepermissions

1
votes

You can try PowerShellAccessControl module I think the details for this module are covered in this youtube video with the function Get-EffectiveAccess. This should help you get the information. The module has been deleted from the Microsoft's PS Gallery. I am not sure how you might be able to install the module from Github, I couldn't try it as I am working with a Mac.