-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathGet-WriteAltSecIDACEs.ps1
123 lines (104 loc) · 4.98 KB
/
Get-WriteAltSecIDACEs.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
Function Get-WriteAltSecIDACEs {
<#
.SYNOPSIS
Get ACEs in the ACL of an AD object that grants write access to AltSecurityIdentities.
Includes Write Alt-Security-Identities and Write Public-Information.
Not including: GenricWrite, WriteProperty all, GenericAll, Owner, WriteOwner, WriteDACL.
.PARAMETER DistinguishedName
Distinguished name of the AD object to get ACL for.
.PARAMETER Domain
DNS name of AD domain. Default: Current domain.
.PARAMETER ExcludeInherited
By default the returned ACL will include inherited ACEs. Use this switch to exclude inherited ACEs.
.EXAMPLE
PS> Get-WriteAltSecIDACEs -DistinguishedName "dc=hackme,dc=local"
Get the ACEs for a single object based on DistinguishedName
.EXAMPLE
PS> Get-ADObject -Filter * -SearchBase "dc=hackme,dc=local" | Get-WriteAltSecIDACEs
Get ACEs of all AD objects under domain root by piping them into Get-WriteAltSecIDACEs
.LINK
https://github.com/JonasBK/Powershell/blob/master/Get-WriteAltSecIDACEs.ps1
.INPUTS
Supports both pipleine from Get-ADObject or a string formatted as DistinguishedName.
#>
[CmdletBinding()]
param (
[Parameter(
Mandatory = $true,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 0
)]
[string]$DistinguishedName,
[Parameter(
Mandatory = $false
)]
[string]$Domain,
[Parameter(
Mandatory = $false
)]
[switch]$ExcludeInherited
)
BEGIN {
# Use current domain if Domian is null
if (($null -eq $Domain) -or ($Domain -eq "")) {
$Domain = (Get-ADDomain).DNSRoot
}
# Get AD schma GUIDs and their Names
### Currently all GUIDs are gathered into a hashtable which is later queried per object. Could be changed so that a lookup is performer per object.
$ADRootDSE = Get-ADRootDSE -Server $Domain
$schemaNamingContext = $ADRootDSE.schemaNamingContext
$configurationNamingContext = $ADRootDSE.configurationNamingContext
# Initialize hashtable
$schemaIDGUID = @{'00000000-0000-0000-0000-000000000000' = 'All'}
Get-ADObject -SearchBase $schemaNamingContext -LDAPFilter '(schemaIDGUID=*)' -Server $Domain -Properties name, schemaIDGUID | ForEach-Object { $schemaIDGUID.add([System.GUID]$_.schemaIDGUID, $_.name) }
Get-ADObject -SearchBase "CN=Extended-Rights,$configurationNamingContext" -LDAPFilter '(objectClass=controlAccessRight)' -Server $Domain -Properties name, rightsGUID | ForEach-Object {
if (!$schemaIDGUID.ContainsKey([System.GUID]$_.rightsGUID)) {
$schemaIDGUID.add([System.GUID]$_.rightsGUID, $_.name)
}
}
# Create PS drive for the select AD domain and jump to that drive
$oldLocation = Get-Location
$adDriveName = "ADDrive-$($Domain.Replace('.','-'))"
if ($oldLocation.Path -ne ($adDriveName + ":\")) {
Get-PSDrive $adDriveName -ErrorAction SilentlyContinue | Remove-PSDrive
$null = New-PSDrive -Name $adDriveName -PSProvider ActiveDirectory -Server $Domain -Root "//RootDSE/"
Set-Location "$($adDriveName):"
}
}
PROCESS {
$resACEs = @()
$acl = Get-Acl -LiteralPath "Microsoft.ActiveDirectory.Management.dll\ActiveDirectory:://RootDSE/$DistinguishedName"
if ($ExcludeInherited) {
$objPermissions = $acl.Access | Where-Object {
($_.IsInherited -eq $false)
}
} else {
$objPermissions = $acl.Access
}
foreach ($permission in $objPermissions) {
$permission | Add-Member -NotePropertyName ObjectDN -NotePropertyValue $DistinguishedName
$permission | Add-Member -NotePropertyName InheritedObjectTypeName -NotePropertyValue $schemaIDGUID[[System.GUID]$permission.inheritedObjectType]
$permission | Add-Member -NotePropertyName ObjectTypeName -NotePropertyValue $schemaIDGUID[[System.GUID]$permission.ObjectType]
# Check if write Alt-Security-Identities
if (($permission.ObjectTypeName -eq "Alt-Security-Identities" -or $Permission.ObjectTypeName -eq "Public-Information") `
-and $permission.AccessControlType -eq "Allow" `
-and $permission.ActiveDirectoryRights -band [System.DirectoryServices.ActiveDirectoryRights]::WriteProperty) {
$resACEs += $permission
}
}
Return $resACEs
}
END {
# Remove the PS drive again
if ($oldLocation.Path -ne ($adDriveName + ":\")) {
try {
Set-Location $oldLocation -ErrorAction Stop
Get-PSDrive $adDriveName -ErrorAction SilentlyContinue | Remove-PSDrive
}
catch [System.Management.Automation.DriveNotFoundException] {
# Stay at current location if our old has been removed
}
}
}
}