Active Directory: Change Object Owner in Bulk

Below you will find scripts that will allow you to mass change the owner of different Active Directory objects such as:

  • Users
  • Groups
  • Organizational Unit
  • Computers

In a “normal” situation, the owner of Active Directory objects is:

  • Domain Admins
  • Company Administrators
  • BUILTIN\Administrators
  • NT AUTHORITY\System

When an object is created by a user who is not a member of one of the above groups through delegation or use of the “Account Operator” group, the user who created the object is the owner.

This situation can pose security issues, if you only have a few objects it is possible to do it by hand, but if you have several dozen/hundreds it can take a lot of time.

The scripts are written with the French name of the groups, you must adapt them according to the language of your Active Directory environment

You can find the scripts here: PowerShell/Active Directory/Fix Owner Objects · master · RDR-IT / Scripts · GitLab

If you only want to display the affected objects:

Users :

# Get Users Owner
# Sources : 
#   - https://blog.piservices.fr/post/2021/03/29/powershell-who-s-owner-of-my-ad-object
#   - https://blog.piservices.fr/post/2021/04/12/powershell-change-the-owner-of-my-ad-objects
#
#   /!\ You must adapt the name of the groups to the installation language of your domain controller /!\
#
#   Dans le cas d'utilisation de ORADAD de ANSSI, le script permet de corriger le probleme : vuln3_owner
#   https://www.cert.ssi.gouv.fr/uploads/guide-ad.html#owner
#
#
# Create Array
$Array = @()
 
# Collect AD infos
$Domain = Get-ADDomain | select -ExpandProperty NetBIOSName
$AllUsers = Get-ADUser -Filter * -Properties nTSecurityDescriptor
 
# Store Info
$AllUsers | foreach {
    $DistinguishedName = $_.DistinguishedName
    $GivenName = $_.GivenName
    $Name = $_.Name
    $ObjectClass = $_.ObjectClass
    $ObjectGUID = $_.ObjectGUID
    $SamAccountName = $_.SamAccountName
    $SID = $_.SID
    $Surname = $_.Surname
    $UserPrincipalName = $_.UserPrincipalName
    $nTSecurityDescriptor = $_.nTSecurityDescriptor
     
     
    $Array += New-Object psobject -Property @{
        DistinguishedName = $DistinguishedName
        GivenName = $GivenName
        Name = $Name
        Owner = $nTSecurityDescriptor.owner
        ObjectClass = $ObjectClass
        ObjectGUID = $ObjectGUID
        SamAccountName = $SamAccountName
        SID = $SID
        Surname = $Surname
        UserPrincipalName = $UserPrincipalName
        }
     
    $DistinguishedName = $null
    $GivenName = $null
    $Name = $null
    $nTSecurityDescriptor = $null
    $ObjectClass = $null
    $ObjectGUID = $null
    $SamAccountName = $null
    $SID = $null
    $Surname = $null
    $UserPrincipalName = $null
    $CurrentUser = $null
    $nTSecurityDescriptor = $null
}

# How many Accounts were returns ?
Write-Host $Array.Count -ForegroundColor Yellow
 
# How many Accounts need to be reviewed ?
$NoGood = $Array.Where({(($_.Owner -ne "$Domain\Admins du domaine") -and ($_.Owner -ne "$Domain\Enterprise Admins") -and ($_.Owner -ne "BUILTIN\Administrateurs") -and ($_.Owner -ne "AUTORITE NT\Système") )})
Write-Host $NoGood.count -ForegroundColor Cyan

# Print NoGood Users with Owner
# $NoGood | ft Name,Owner

$Filter = $NoGood.Where({$_.Name -notlike "SystemMailbox*"})
$Filter = $Filter.Where({$_.Name -notlike "HealthMailbox*"})

# Print NoGood Users with Owner
$Filter | ft Name,Owner

# For Debug : check difference between normal object and exchange object
#Write-Host $NoGood.count -ForegroundColor Cyan
Write-Host $Filter.count -ForegroundColor Red

Computers:

# Get Computer Owner
# Sources : 
#   - https://blog.piservices.fr/post/2021/03/29/powershell-who-s-owner-of-my-ad-object
#   - https://blog.piservices.fr/post/2021/04/12/powershell-change-the-owner-of-my-ad-objects
#
#   /!\ You must adapt the name of the groups to the installation language of your domain controller /!\
#
#   Dans le cas d'utilisation de ORADAD de ANSSI, le script permet de corriger le probleme : vuln3_owner
#   https://www.cert.ssi.gouv.fr/uploads/guide-ad.html#owner
#
#
# Create Array
$Array = @()

# Collect AD infos
$Domain = Get-ADDomain | select -ExpandProperty NetBIOSName
$AllComputers = Get-ADComputer -Filter * -Properties nTSecurityDescriptor
 
# Store Info
$AllComputers | foreach {
    $DistinguishedName = $_.DistinguishedName
    $GroupCategory = $_.GroupCategory
    $GroupScope = $_.GroupScope
    $Name = $_.Name
    $ObjectClass = $_.ObjectClass
    $ObjectGUID = $_.ObjectGUID
    $SamAccountName = $_.SamAccountName
    $SID = $_.SID
    $nTSecurityDescriptor = $_.nTSecurityDescriptor
     
     
    $Array += New-Object psobject -Property @{
        DistinguishedName = $DistinguishedName
        DNSHostName = $DNSHostName
        Enabled = $Enabled
        Name = $Name
        ObjectClass = $ObjectClass
        ObjectGUID = $ObjectGUID
        SamAccountName = $SamAccountName
        SID = $SID
        Owner = $nTSecurityDescriptor.owner
        }
     
    $DistinguishedName = $null
    $DNSHostName = $null
    $Enabled = $null
    $Name = $null
    $ObjectClass = $null
    $ObjectGUID = $null
    $SamAccountName = $null
    $SID = $null
    $nTSecurityDescriptor = $null
    }
 
# How many Accounts were returns ?
Write-Host $Array.Count -ForegroundColor Yellow
 
# How many Accounts need to be reviewed ?
$NoGood = $Array.Where({(($_.Owner -ne "$Domain\Admins du domaine") -and ($_.Owner -ne "$Domain\Enterprise Admins") -and ($_.Owner -ne "BUILTIN\Administrateurs") -and ($_.Owner -ne "AUTORITE NT\Système") )})
Write-Host $NoGood.count -ForegroundColor Cyan
Write-Host $NoGood

Groupe :

# Fix Group Owner
# Sources : 
#   - https://blog.piservices.fr/post/2021/03/29/powershell-who-s-owner-of-my-ad-object
#   - https://blog.piservices.fr/post/2021/04/12/powershell-change-the-owner-of-my-ad-objects
#
#   /!\ You must adapt the name of the groups to the installation language of your domain controller /!\
#
#   Dans le cas d'utilisation de ORADAD de ANSSI, le script permet de corriger le probleme : vuln3_owner
#   https://www.cert.ssi.gouv.fr/uploads/guide-ad.html#owner
#
#

# Create Array
$Array = @()
 
# Collect AD infos
$Domain = Get-ADDomain | select -ExpandProperty NetBIOSName
$AllGroups = Get-ADGroup -Filter * -Properties nTSecurityDescriptor
 
# Store Info
$AllGroups | foreach {
    $DistinguishedName = $_.DistinguishedName
    $GroupCategory = $_.GroupCategory
    $GroupScope = $_.GroupScope
    $Name = $_.Name
    $ObjectClass = $_.ObjectClass
    $ObjectGUID = $_.ObjectGUID
    $SamAccountName = $_.SamAccountName
    $SID = $_.SID
    $nTSecurityDescriptor = $_.nTSecurityDescriptor
     
     
    $Array += New-Object psobject -Property @{
        DistinguishedName = $DistinguishedName
        GroupCategory = $GroupCategory
        GroupScope = $GroupScope
        Name = $Name
        ObjectClass = $ObjectClass
        ObjectGUID = $ObjectGUID
        SamAccountName = $SamAccountName
        SID = $SID
        Owner = $nTSecurityDescriptor.owner
        }
     
    $DistinguishedName = $null
    $DNSHostName = $null
    $Enabled = $null
    $Name = $null
    $ObjectClass = $null
    $ObjectGUID = $null
    $SamAccountName = $null
    $SID = $null
    $nTSecurityDescriptor = $null
}
 
# How many Accounts were returns ?
Write-Host $Array.Count -ForegroundColor Yellow
 
# How many Accounts need to be reviewed ?
$NoGood = $Array.Where({(($_.Owner -ne "$Domain\Admins du domaine") -and ($_.Owner -ne "$Domain\Enterprise Admins") -and ($_.Owner -ne "BUILTIN\Administrateurs") -and ($_.Owner -ne "AUTORITE NT\Système") )})
Write-Host $NoGood.count -ForegroundColor Cyan

# Print NoGood Groups with Owner
$NoGood | ft Name,Owner

Organizational Unit:

# Get OU Owner
# Sources : 
#   - https://blog.piservices.fr/post/2021/03/29/powershell-who-s-owner-of-my-ad-object
#   - https://blog.piservices.fr/post/2021/04/12/powershell-change-the-owner-of-my-ad-objects
#
#   /!\ You must adapt the name of the groups to the installation language of your domain controller /!\
#
#   Dans le cas d'utilisation de ORADAD de ANSSI, le script permet de corriger le probleme : vuln3_owner
#   https://www.cert.ssi.gouv.fr/uploads/guide-ad.html#owner
#
#
# Create Array
$Array = @()
 
# Collect AD infos
$Domain = Get-ADDomain | select -ExpandProperty NetBIOSName
$AllOU = Get-ADOrganizationalUnit -Filter * -Properties nTSecurityDescriptor
 
# Store Info
$AllOU | foreach {
    $City = $_.City
    $Country = $_.Country
    $DistinguishedName = $_.DistinguishedName
    $ManagedBy = $_.ManagedBy
    $Name = $_.Name
    $nTSecurityDescriptor = $_.nTSecurityDescriptor
     
     
    $Array += New-Object psobject -Property @{
        City = $City
        Country = $Country
        DistinguishedName = $DistinguishedName
        ManagedBy = $ManagedBy
        Name = $Name
        Owner = $nTSecurityDescriptor.owner
        }
     
    $City = $null
    $Country = $null
    $DistinguishedName = $null
    $ManagedBy = $null
    $Name = $null
    $nTSecurityDescriptor = $null
    }
 
# How many Accounts were returns ?
Write-Host $Array.Count -ForegroundColor Yellow
 
# How many Accounts need to be reviewed ?
$NoGood = $Array.Where({(($_.Owner -ne "$Domain\Admins du domaine") -and ($_.Owner -ne "$Domain\Enterprise Admins") -and ($_.Owner -ne "BUILTIN\Administrateurs") -and ($_.Owner -ne "AUTORITE NT\Système") )})
Write-Host $NoGood.count -ForegroundColor Cyan

$NoGood | ft Name,Owner

Sources :

Romain Drouche
System Architect | MCSE: Core Infrastructure
IT infrastructure expert with over 15 years of field experience. Currently a Systems and Networks Project Manager and Information Systems Security (ISS) expert, I use my expertise to ensure the reliability and security of technological environments.

Leave a Comment