Skip to content

Instantly share code, notes, and snippets.

@HopHouse
Last active April 15, 2021 07:52
Show Gist options
  • Save HopHouse/7653ace88400c79c67bf14fba45cd4c2 to your computer and use it in GitHub Desktop.
Save HopHouse/7653ace88400c79c67bf14fba45cd4c2 to your computer and use it in GitHub Desktop.
# Associated blog post : https://blog.hophouse.fr/_posts/CheckResetPasswordRights.html
function Get-ADAllUserGroupMembership {
<#
.SYNOPSIS
Recursively retrieve all the groups where a specified group belongs to.
.EXAMPLE
PS> Get-ADAllUserGroupMembership -Server 10.10.10.10 -GroupName custom_admin
.PARAMETER Server
Domain Controller where to run commands.
.PARAMETER GroupName
Group where the function will dig.
#>
[CmdletBinding()]
param(
[parameter(mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string]$Server,
[parameter(mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string]$GroupName
)
$GroupMembership = @()
$GroupObject = Get-ADGroup -Server $Server -Identity $GroupName -Properties MemberOf,objectSid
[array]$GroupMembership += $GroupObject
$GroupMemberObject = ($GroupObject).MemberOf
if($GroupMemberObject.count -eq 0) {
return $GroupMembership
}
foreach ($grp in $GroupMemberObject) {
[array]$GroupMembership += Get-ADAllUserGroupMembership -Server $Server -GroupName $grp
}
return $GroupMembership | Sort-Object -Unique
}
function Invoke-CheckResetUserPasswordRight {
<#
.SYNOPSIS
Retrieve the users that the specified users are able to reset the password.
.EXAMPLE
PS> Invoke-CheckResetUserPasswordRight -Server 10.10.10.10 -Users User1
PS> Invoke-CheckResetUserPasswordRight -Server 10.10.10.10 -Users User1 -Filter 'enabled -eq $true'
PS> Invoke-CheckResetUserPasswordRight -Server 10.10.10.10 -Users User1 -Filter "Name -like '*user*'"
PS> Invoke-CheckResetUserPasswordRight -Server 10.10.10.10 -Users User1,User2 -SearchBase "OU=Admins,DC=lab,DC=local"
PS> Invoke-CheckResetUserPasswordRight -Server 10.10.10.10 -Users User1,User2,User3 -NoGroupCheck -OnlyResult
.PARAMETER Server
Domain Controller where to run commands.
.PARAMETER Users
List of users to check.
.PARAMETER Filter
Filter applied to the Get-AdUser function.
.PARAMETER Filter
Apply a search base to the function Get-AdUser.
.PARAMETER OnlyResults
Display only the samAccountName of users where specified users can reset the password.
.PARAMETER OnlyResults
Search only direct right to reset password and do not include groups of the user.
#>
[CmdletBinding()]
[OutputType([hashtable])]
param(
[parameter(mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string]$Server,
[parameter(mandatory=$True)]
[ValidateNotNullOrEmpty()]
[array]$Users,
[parameter(mandatory=$False)]
[string]$Filter = "*",
[parameter(mandatory=$False)]
[ValidateNotNullOrEmpty()]
[string]$SearchBase = "",
[switch]$OnlyResults,
[switch]$NoGroupCheck
)
try {
Import-Module ActiveDirectory
}
catch {
Write-Host "[!] Please install the ActiveDirectory module"
return
}
$ResultRestPasswordRight = @()
$objects = @()
# Default values for ObjectType GUID - CN=User-Force-Change-Password,CN=Extended-Rights,CN=Configuration,DC=lab,DC=local
$RestPasswordRight = "00299570-246d-11d0-a768-00aa006e0529"
#$ChangePasswordRight = "ab721a53-1e2f-11d0-9819-00aa0040529b"
$GenericAllRight = "00000000-0000-0000-0000-000000000000"
# Mount the AD as drive in order to get ACL on its objects
Write-Output "[+] Mount AD drive"
New-PSDrive -Name AD -PSProvider ActiveDirectory -Root "//RootDSE/" -Server $Server | Out-Null
# Get user information
foreach ($User in $Users) {
Echo "[+] Get User informations for $User"
$userInfo = Get-ADUser -Server $Server -Identity $User -Properties MemberOf
if ($userInfo -eq $null) {
return
}
[array]$objects += $userInfo
$userGroups = ($userInfo).MemberOf
if ($NoGroupCheck.IsPresent -eq $True) {
break
}
Write-Output "[+] Get groups for $User"
($userGroups) | ForEach-Object {
[array]$objects += Get-ADAllUserGroupMembership -Server $Server -GroupName $_
}
if ($userGroups.count -ge 1) {
Write-Output "[+] $User belongs to :"
($objects[1..($objects.Length-1)]) | ForEach-Object {
Write-Output " - [$($_.objectSid)] $($_.samAccountName)"
}
} else {
Write-Output " [+] $User does not belong to any group."
}
$objects = ($objects | Sort-Object -Unique)
}
Write-Output "[+] Get all users"
if ($SearchBase -ne "") {
$allUsers = Get-ADUser -Server $Server -Filter $Filter -SearchBase $SearchBase
} else {
$allUsers = Get-ADUser -Server $Server -Filter $Filter
}
Write-Output "[+] Run search on $($allUsers.count) users at $(Get-Date)"
($allUsers) | ForEach-Object {
$targetUser = $_
# Get ACL to reset password right
try {
$aclResetPassword = ((Get-Acl "AD:\$($targetUser.DistinguishedName)" | Select-object Access).access| Where-Object {$_.ObjectType -eq $RestPasswordRight -or $_.InheritedObjectType -eq $ResetPasswordRight -or $_.ObjectType -eq $GenericAllRight})
}
catch { }
($objects) | ForEach-Object {
$object = $_
$acl = $aclResetPassword | Where-Object {$_.IdentityReference -like "*$($object.SamAccountName)" -or $_.IdentityReference -eq $object.SID}
if ($acl -ne $null) {
$properties = @{
From = $object.samAccountName
PasswordResetRight = $true
User = $targetUser.samAccountName
UserIsEnabled = $targetUser.Enabled
}
$obj = New-Object -TypeName psobject -Property $properties
$ResultRestPasswordRight += $obj
}
}
}
Write-Output "[+] Finished search on $($allUsers.count) users at $(Get-Date)"
if ($OnlyResults -eq $True) {
return ($ResultRestPasswordRight).User | Sort-Object -Unique
}
if ($ResultRestPasswordRight.Length -ge 1) {
Write-Output "`r`n[+] CMD : Set-ADAccountPassword -Server $($Server) -identity User -Reset -NewPassword (ConvertTo-SecureString -AsPlainText 'Password' -Force)"
}
return $ResultRestPasswordRight
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment