@@ -6590,6 +6590,20 @@ function Get-NetGPOGroup {
6590
6590
6591
6591
Returns all GPOs in a domain that set "Restricted Groups" or use groups.xml on on target machines.
6592
6592
6593
+ Author: @harmj0y
6594
+ License: BSD 3-Clause
6595
+ Required Dependencies: Get-NetGPO, Get-GptTmpl, Get-GroupsXML, Convert-NameToSid, Convert-SidToName
6596
+ Optional Dependencies: None
6597
+
6598
+ . DESCRIPTION
6599
+
6600
+ First enumerates all GPOs in the current/target domain using Get-NetGPO with passed
6601
+ arguments, and for each GPO checks if 'Restricted Groups' are set with GptTmpl.inf or
6602
+ group membership is set through Group Policy Preferences groups.xml files. For any
6603
+ GptTmpl.inf files found, the file is parsed with Get-GptTmpl and any 'Group Membership'
6604
+ section data is processed if present. Any found Groups.xml files are parsed with
6605
+ Get-GroupsXML and those memberships are returned as well.
6606
+
6593
6607
. PARAMETER GPOname
6594
6608
6595
6609
The GPO name to query for, wildcards accepted.
@@ -6628,6 +6642,10 @@ function Get-NetGPOGroup {
6628
6642
PS C:\> Get-NetGPOGroup
6629
6643
6630
6644
Returns all local groups set by GPO along with their members and memberof.
6645
+
6646
+ . LINK
6647
+
6648
+ https://morgansimonsenblog.azurewebsites.net/tag/groups/
6631
6649
#>
6632
6650
6633
6651
[CmdletBinding ()]
@@ -6683,13 +6701,14 @@ function Get-NetGPOGroup {
6683
6701
ForEach ($Membership in $Inf .' Group Membership' .GetEnumerator()) {
6684
6702
$Group , $Relation = $Membership.Key.Split (' __' , $Option ) | ForEach-Object {$_.Trim ()}
6685
6703
6704
+ # extract out ALL members
6686
6705
$MembershipValue = $Membership.Value.Split (' ,' ) | ForEach-Object { $_.Trim (' *' ) } | Where-Object {$_ }
6687
6706
if ($MembershipValue -isnot [System.Array ]) { $MembershipValue = @ ($MembershipValue ) }
6688
6707
6689
6708
if ($ResolveMemberSIDs ) {
6709
+ # if the resulting member is username and not a SID, attempt to resolve it
6690
6710
$GroupMembers = @ ()
6691
6711
ForEach ($Member in $MembershipValue ) {
6692
- Write-Verbose " Member: $Member "
6693
6712
if ($Member -notmatch ' ^S-1-.*' ) {
6694
6713
$MemberSID = Convert-NameToSid - ObjectName $Member | Select-Object - ExpandProperty SID
6695
6714
if ($MemberSID ) {
@@ -6714,7 +6733,7 @@ function Get-NetGPOGroup {
6714
6733
6715
6734
ForEach ($Membership in $Memberships.GetEnumerator ()) {
6716
6735
if ($Membership.Key -match ' ^\*' ) {
6717
- # if the SID is already resolved, try to resolve SID to a name
6736
+ # if the SID is already resolved (i.e. begins with *) try to resolve SID to a name
6718
6737
$GroupSID = $Membership.Key.Trim (' *' )
6719
6738
$GroupName = Convert-SidToName - SID $GroupSID
6720
6739
}
@@ -6739,6 +6758,7 @@ function Get-NetGPOGroup {
6739
6758
$GPOGroup | Add-Member Noteproperty ' GPODisplayName' $GPODisplayName
6740
6759
$GPOGroup | Add-Member Noteproperty ' GPOName' $GPOName
6741
6760
$GPOGroup | Add-Member Noteproperty ' GPOPath' $GPOPath
6761
+ $GPOGroup | Add-Member Noteproperty ' GPOType' ' RestrictedGroups'
6742
6762
$GPOGroup | Add-Member Noteproperty ' Filters' $Null
6743
6763
$GPOGroup | Add-Member Noteproperty ' GroupName' $GroupName
6744
6764
$GPOGroup | Add-Member Noteproperty ' GroupSID' $GroupSID
@@ -6758,6 +6778,7 @@ function Get-NetGPOGroup {
6758
6778
$GroupMembers = @ ()
6759
6779
ForEach ($Member in $_.GroupMembers ) {
6760
6780
if ($Member -notmatch ' ^S-1-.*' ) {
6781
+ # if the resulting member is username and not a SID, attempt to resolve it
6761
6782
$MemberSID = Convert-NameToSid - ObjectName $Member | Select-Object - ExpandProperty SID
6762
6783
if ($MemberSID ) {
6763
6784
$GroupMembers += $MemberSID
@@ -6775,6 +6796,7 @@ function Get-NetGPOGroup {
6775
6796
6776
6797
$_ | Add-Member Noteproperty ' GPODisplayName' $GPODisplayName
6777
6798
$_ | Add-Member Noteproperty ' GPOName' $GPOName
6799
+ $_ | Add-Member Noteproperty ' GPOType' ' GroupPolicyPreferences'
6778
6800
$_
6779
6801
}
6780
6802
}
@@ -6784,10 +6806,19 @@ function Get-NetGPOGroup {
6784
6806
function Find-GPOLocation {
6785
6807
<#
6786
6808
. SYNOPSIS
6809
+
6810
+ Enumerates the machines where a specific user/group is a member of a specific
6811
+ local group, all through GPO correlation.
6787
6812
6788
- Takes a user/group name and optional domain, and determines
6789
- the computers in the domain the user/group has local admin
6790
- (or RDP) rights to.
6813
+ Author: @harmj0y
6814
+ License: BSD 3-Clause
6815
+ Required Dependencies: Get-NetUser, Get-NetGroup, Get-NetGPOGroup, Get-NetOU, Get-NetComputer, Get-ADObject, Get-NetSite
6816
+ Optional Dependencies: None
6817
+
6818
+ . DESCRIPTION
6819
+
6820
+ Takes a user/group name and optional domain, and determines the computers in the domain
6821
+ the user/group has local admin (or RDP) rights to.
6791
6822
6792
6823
It does this by:
6793
6824
1. resolving the user/group to its proper SID
@@ -6800,6 +6831,9 @@ function Find-GPOLocation {
6800
6831
5. enumerating all OUs and sites and applicable GPO GUIs are
6801
6832
applied to through gplink enumerating
6802
6833
6. querying for all computers under the given OUs or sites
6834
+
6835
+ If no user/group is specified, all user/group -> machine mappings discovered through
6836
+ GPO relationships are returned.
6803
6837
6804
6838
. PARAMETER UserName
6805
6839
@@ -6831,6 +6865,13 @@ function Find-GPOLocation {
6831
6865
6832
6866
The PageSize to set for the LDAP searcher object.
6833
6867
6868
+ . EXAMPLE
6869
+
6870
+ PS C:\> Find-GPOLocation
6871
+
6872
+ Find all user/group -> machine relationships where the user/group is a member
6873
+ of the local administrators group on target machines.
6874
+
6834
6875
. EXAMPLE
6835
6876
6836
6877
PS C:\> Find-GPOLocation -UserName dfm
@@ -6878,11 +6919,11 @@ function Find-GPOLocation {
6878
6919
)
6879
6920
6880
6921
if ($UserName ) {
6881
-
6922
+ # if a group name is specified, get that user object so we can extract the target SID
6882
6923
$User = Get-NetUser - UserName $UserName - Domain $Domain - DomainController $DomainController - PageSize $PageSize
6883
6924
$UserSid = $User.objectsid
6884
6925
6885
- if (! $UserSid ) {
6926
+ if (-not $UserSid ) {
6886
6927
Throw " User '$UserName ' not found!"
6887
6928
}
6888
6929
@@ -6891,11 +6932,11 @@ function Find-GPOLocation {
6891
6932
$TargetObject = $UserSid
6892
6933
}
6893
6934
elseif ($GroupName ) {
6894
-
6935
+ # if a group name is specified, get that group object so we can extract the target SID
6895
6936
$Group = Get-NetGroup - GroupName $GroupName - Domain $Domain - DomainController $DomainController - FullData - PageSize $PageSize
6896
6937
$GroupSid = $Group.objectsid
6897
6938
6898
- if (! $GroupSid ) {
6939
+ if (-not $GroupSid ) {
6899
6940
Throw " Group '$GroupName ' not found!"
6900
6941
}
6901
6942
@@ -6907,6 +6948,7 @@ function Find-GPOLocation {
6907
6948
$TargetSIDs = @ (' *' )
6908
6949
}
6909
6950
6951
+ # figure out what the SID is of the target local group we're checking for membership in
6910
6952
if ($LocalGroup -like " *Admin*" ) {
6911
6953
$TargetLocalSID = ' S-1-5-32-544'
6912
6954
}
@@ -6920,8 +6962,9 @@ function Find-GPOLocation {
6920
6962
throw " LocalGroup must be 'Administrators', 'RDP', or a 'S-1-5-X' SID format."
6921
6963
}
6922
6964
6965
+ # if we're not listing all relationships, use the tokenGroups approach from Get-NetGroup to
6966
+ # get all effective security SIDs this object is a part of
6923
6967
if ($TargetSIDs [0 ] -and ($TargetSIDs [0 ] -ne ' *' )) {
6924
- # use the tokenGroups approach from Get-NetGroup to get all effective security SIDs this object is a part of
6925
6968
$TargetSIDs += Get-NetGroup - Domain $Domain - DomainController $DomainController - PageSize $PageSize - UserName $ObjectSamAccountName - RawSids
6926
6969
}
6927
6970
@@ -6940,6 +6983,7 @@ function Find-GPOLocation {
6940
6983
' PageSize' = $PageSize
6941
6984
}
6942
6985
6986
+ # enumerate all GPO group mappings for the target domain
6943
6987
$GPOgroups = Get-NetGPOGroup @GPOGroupArgs | ForEach-Object {
6944
6988
6945
6989
$GPOgroup = $_
@@ -6960,26 +7004,24 @@ function Find-GPOLocation {
6960
7004
$GPOname = $_.GPODisplayName
6961
7005
$GPOguid = $_.GPOName
6962
7006
$GPOPath = $_.GPOPath
7007
+ $GPOType = $_.GPOType
6963
7008
$GPOMembers = $_.GroupMembers
6964
7009
$Filters = $_.Filters
6965
7010
6966
7011
if (-not $TargetObject ) {
6967
7012
# if the * wildcard was used, set the ObjectDistName as the GPO member SID set
6968
- $TargetObject = $GPOMembers
6969
- }
6970
-
6971
- if ($GPOName -match ' Groups.xml' ) {
6972
- $GPOType = ' GroupPolicyPreferences'
7013
+ # so all relationship mappings are output
7014
+ $TargetObjectSIDs = $GPOMembers
6973
7015
}
6974
7016
else {
6975
- $GPOType = ' RestrictedGroups '
7017
+ $TargetObjectSIDs = $TargetObject
6976
7018
}
6977
7019
6978
7020
# find any OUs that have this GUID applied and then retrieve any computers from the OU
6979
7021
Get-NetOU - Domain $Domain - DomainController $DomainController - GUID $GPOguid - FullData - PageSize $PageSize | ForEach-Object {
6980
7022
if ($Filters ) {
6981
7023
# filter for computer name/org unit if a filter is specified
6982
- # TODO: handle other filters (i.e. OU filters?)
7024
+ # TODO: handle other filters (i.e. OU filters?) again, I hate you GPP...
6983
7025
$OUComputers = Get-NetComputer - Domain $Domain - DomainController $DomainController - Credential $Credential - ADSpath $_.ADSpath - FullData - PageSize $PageSize | Where-Object {
6984
7026
$_.adspath -match ($Filters.Value )
6985
7027
} | ForEach-Object { $_.dnshostname }
@@ -6990,7 +7032,7 @@ function Find-GPOLocation {
6990
7032
6991
7033
if ($OUComputers -isnot [System.Array ]) {$OUComputers = @ ($OUComputers )}
6992
7034
6993
- ForEach ($TargetSid in $TargetObject ) {
7035
+ ForEach ($TargetSid in $TargetObjectSIDs ) {
6994
7036
6995
7037
$Object = Get-ADObject - SID $TargetSid - Domain $Domain - DomainController $DomainController $_ - PageSize $PageSize
6996
7038
@@ -7014,7 +7056,7 @@ function Find-GPOLocation {
7014
7056
# find any sites that have this GUID applied
7015
7057
Get-NetSite - Domain $Domain - DomainController $DomainController - GUID $GPOguid - PageSize $PageSize - FullData | ForEach-Object {
7016
7058
7017
- ForEach ($TargetSid in $TargetObject ) {
7059
+ ForEach ($TargetSid in $TargetObjectSIDs ) {
7018
7060
$Object = Get-ADObject - SID $TargetSid - Domain $Domain - DomainController $DomainController $_ - PageSize $PageSize
7019
7061
7020
7062
$IsGroup = @ (' 268435456' , ' 268435457' , ' 536870912' , ' 536870913' ) -contains $Object.samaccounttype
@@ -7041,8 +7083,23 @@ function Find-GPOComputerAdmin {
7041
7083
<#
7042
7084
. SYNOPSIS
7043
7085
7044
- Takes a computer (or GPO) object and determines what users/groups have
7045
- administrative access over it.
7086
+ Takes a computer (or GPO) object and determines what users/groups are in the specified
7087
+ local group for the machine.
7088
+
7089
+ Author: @harmj0y
7090
+ License: BSD 3-Clause
7091
+ Required Dependencies: Get-NetComputer, Get-SiteName, Get-NetSite, Get-NetGPOGroup, Get-ADObject, Get-NetGroupMember, Convert-SidToName
7092
+ Optional Dependencies: None
7093
+
7094
+ . DESCRIPTION
7095
+
7096
+ If a -ComputerName is specified, retrieve the complete computer object, attempt to
7097
+ determine the OU the computer is a part of. Then resolve the computer's site name with
7098
+ Get-SiteName and retrieve all sites object Get-NetSite. For those results, attempt to
7099
+ enumerate all linked GPOs and associated local group settings with Get-NetGPOGroup. For
7100
+ each resulting GPO group, resolve the resulting user/group name to a full AD object and
7101
+ return the results. This will return the domain objects that are members of the specified
7102
+ -LocalGroup for the given computer.
7046
7103
7047
7104
Inverse of Find-GPOLocation.
7048
7105
@@ -7211,13 +7268,6 @@ function Find-GPOComputerAdmin {
7211
7268
$GPOgroups | Sort-Object - Property GPOName - Unique | ForEach-Object {
7212
7269
$GPOGroup = $_
7213
7270
7214
- if ($GPOGroup.GPOPath -match ' Groups.xml' ) {
7215
- $GPOType = ' GroupPolicyPreferences'
7216
- }
7217
- else {
7218
- $GPOType = ' RestrictedGroups'
7219
- }
7220
-
7221
7271
$GPOGroup.GroupMembers | ForEach-Object {
7222
7272
7223
7273
# resolve this SID to a domain object
@@ -7234,7 +7284,7 @@ function Find-GPOComputerAdmin {
7234
7284
$GPOComputerAdmin | Add-Member Noteproperty ' GPODisplayName' $GPOGroup.GPODisplayName
7235
7285
$GPOComputerAdmin | Add-Member Noteproperty ' GPOGuid' $GPOGroup.GPOName
7236
7286
$GPOComputerAdmin | Add-Member Noteproperty ' GPOPath' $GPOGroup.GPOPath
7237
- $GPOComputerAdmin | Add-Member Noteproperty ' GPOType' $GPOType
7287
+ $GPOComputerAdmin | Add-Member Noteproperty ' GPOType' $GPOType.GPOType
7238
7288
$GPOComputerAdmin
7239
7289
7240
7290
# if we're recursing and the current result object is a group
0 commit comments