0

Update: So I changed some information in the script, and it works as intended when I am running it as a Domain Admin but I prefer not to give a service account DA Rights if I can avoid it, I am just not understanding why the Service Account is not using the rights I gave it in Group Policy to take ownership, is there something else I have to do?

Here is the updated Code:

$NewOwner = (Get-ADServiceAccount SVC._DA001).samAccountName
$Domains = (Get-ADForest).Domains

ForEach($Domain in $Domains){

$Identities1 = Get-ADObject -Filter * -Server $Domain -Properties objectClass | Where {$_.objectClass -eq $null}
$Identities2 = Get-ADComputer -Filter * -Properties samAccountName,memberOf,adminCount -Server $Domain | Where {$_.adminCount -lt 1}
$Identities3 = Get-ADGroup -Filter * -Properties samAccountName,memberOf,adminCount -Server $Domain | Where {$_.adminCount -lt 1}
$Identities4 = Get-ADServiceAccount -Filter * -Properties samAccountName,memberOf,adminCount -Server $Domain | Where {$_.adminCount -lt 1}
$Identities5 = Get-ADUser -Filter * -Properties samAccountName,memberOf,adminCount -Server $Domain | Where {$_.adminCount -lt 1}
$baseDN = (Get-ADDomain $Domain).DistinguishedName


$Server = (Get-ADDomainController -Server $Domain).name

Import-Module ActiveDirectory
New-PSDrive -Name ADDOM -PSProvider ActiveDirectory -Server $Domain -Scope Global -Root "//ROOTDSE/" | Out-Null


if (!($Identities1 -eq $null)){
foreach ($obj in $Identities1) {

  $DN = $obj.distinguishedName
  if (!($obj.memberOf -like "*Permissions Auditor Exemption*"))
  {
  Write-Host $DN
    #First Set the Owner to the SVC Account.
    $acl = get-acl -Path "ADDOM:CN=Users,$baseDN"
    $acl.SetOwner([Security.Principal.NTaccount]($NewOwner))
    set-acl -path ADDOM:$DN -AclObject $acl
    Start-Sleep -s 2



# get explicit permissions

$acl = Get-Acl -Path ADDOM:$DN
# Set inheritance to true
$acl.SetAccessRuleProtection($false,$false)
$acl.Access |
  # ...find all not inherited permissions.
  Where-Object { $_.isInherited -eq $false } |
  # ...and remove them
  ForEach-Object { $acl.RemoveAccessRule($_) } 

# set new permissions
$acl | Set-Acl -Path ADDOM:$DN

        
}


}

}

foreach ($obj in $Identities2) {

  $DN = $obj.distinguishedName
  if (!($obj.memberOf -like "*Permissions Auditor Exemption*"))
  {
  Write-Host $DN
    #First Set the Owner to the SVC Account.
    $acl = get-acl -Path ADDOM:$DN
    $acl.SetOwner([Security.Principal.NTaccount]($NewOwner))
    set-acl -path ADDOM:$DN -AclObject $acl
    Start-Sleep -s 2



# get explicit permissions

$acl = Get-Acl -Path ADDOM:$DN
# Set inheritance to true
$acl.SetAccessRuleProtection($false,$false)
$acl.Access |
  # ...find all not inherited permissions.
  Where-Object { $_.isInherited -eq $false } |
  # ...and remove them
  ForEach-Object { $acl.RemoveAccessRule($_) } 

# set new permissions
$acl | Set-Acl -Path ADDOM:$DN

        
}


}


foreach ($obj in $Identities3) {

  $DN = $obj.distinguishedName
  if (!($obj.memberOf -like "*Permissions Auditor Exemption*"))
  {
  Write-Host $DN
    #First Set the Owner to the SVC Account.
    $acl = get-acl -Path ADDOM:$DN
    $acl.SetOwner([Security.Principal.NTaccount]($NewOwner))
    set-acl -path ADDOM:$DN -AclObject $acl
    Start-Sleep -s 2



# get explicit permissions

$acl = Get-Acl -Path ADDOM:$DN
# Set inheritance to true
$acl.SetAccessRuleProtection($false,$false)
$acl.Access |
  # ...find all not inherited permissions.
  Where-Object { $_.isInherited -eq $false } |
  # ...and remove them
  ForEach-Object { $acl.RemoveAccessRule($_) } 

# set new permissions
$acl | Set-Acl -Path ADDOM:$DN

        
}


}


foreach ($obj in $Identities4) {

  $DN = $obj.distinguishedName
  if (!($obj.memberOf -like "*Permissions Auditor Exemption*"))
  {
  Write-Host $DN
    #First Set the Owner to the SVC Account.
    $acl = get-acl -Path ADDOM:$DN
    $acl.SetOwner([Security.Principal.NTaccount]($NewOwner))
    set-acl -path ADDOM:$DN -AclObject $acl
    Start-Sleep -s 2



# get explicit permissions

$acl = Get-Acl -Path ADDOM:$DN
# Set inheritance to true
$acl.SetAccessRuleProtection($false,$false)
$acl.Access |
  # ...find all not inherited permissions.
  Where-Object { $_.isInherited -eq $false } |
  # ...and remove them
  ForEach-Object { $acl.RemoveAccessRule($_) } 

# set new permissions
$acl | Set-Acl -Path ADDOM:$DN

        
}


}


foreach ($obj in $Identities5) {

  $DN = $obj.distinguishedName
  if (!($obj.memberOf -like "*Permissions Auditor Exemption*"))
  {
  Write-Host $DN
    #First Set the Owner to the SVC Account.
    $acl = get-acl -Path ADDOM:$DN
    $acl.SetOwner([Security.Principal.NTaccount]($NewOwner))
    set-acl -path ADDOM:$DN -AclObject $acl
    Start-Sleep -s 2



# get explicit permissions

$acl = Get-Acl -Path ADDOM:$DN
# Set inheritance to true
$acl.SetAccessRuleProtection($false,$false)
$acl.Access |
  # ...find all not inherited permissions.
  Where-Object { $_.isInherited -eq $false } |
  # ...and remove them
  ForEach-Object { $acl.RemoveAccessRule($_) } 

# set new permissions
$acl | Set-Acl -Path ADDOM:$DN

        
}


}



Remove-PSDrive ADDOM
}

Having trouble with this PS Script. I am attempting to use it to find all active directory objects and take ownership of them as well as reset any custom permissions that have been added to the objects.

The reason for this is to prevent lower level administrators from going in adding any backdoor permissions for individuals/groups that shouldn't have rights over those objects.

I have added my service account used for this process to the "Take Ownership of Files and other objects" Group Policy Right as well so there should be no problems.

$NewOwner = (Get-ADServiceAccount SVC._DA001).samAccountName
$Domains = (Get-ADForest).Domains

ForEach($Domain in $Domains){

$Identities1 = Get-ADObject -Filter * -Server $Domain -Properties objectClass | Where {$_.objectClass -eq $null}
$Identities2 = Get-ADComputer -Filter * -Properties samAccountName,memberOf,adminCount -Server $Domain | Where {$_.adminCount -lt 1}
$Identities3 = Get-ADGroup -Filter * -Properties samAccountName,memberOf,adminCount -Server $Domain | Where {$_.adminCount -lt 1}
$Identities4 = Get-ADServiceAccount -Filter * -Properties samAccountName,memberOf,adminCount -Server $Domain | Where {$_.adminCount -lt 1}
$Identities5 = Get-ADUser -Filter * -Properties samAccountName,memberOf,adminCount -Server $Domain | Where {$_.adminCount -lt 1}
$baseDN = (Get-ADDomain $Domain).DistinguishedName
if ($Identities1){
$Identities = $Identities1 + $Identities2 + $Identities3 + $Identities4 + $Identities5
}
Else{
$Identities = $Identities2 + $Identities3 + $Identities4 + $Identities5
}

$Server = (Get-ADDomainController -Server $Domain).name

Import-Module ActiveDirectory
New-PSDrive -Name ADDOM -PSProvider ActiveDirectory -Server $Domain -Scope Global -Root "//ROOTDSE/" | Out-Null



foreach ($obj in $Identities) {

  $DN = $obj.distinguishedName
  if (!($obj.memberOf -like "*Permissions Auditor Exemption*"))
  {
  Write-Host $DN
    #First Set the Owner to the SVC Account.
    $acl = get-acl -Path "ADDOM:CN=Users,$baseDN"
    $acl.SetOwner([Security.Principal.NTaccount]($NewOwner))
    set-acl -path ADDOM:$DN -AclObject $acl
    Start-Sleep -s 2



# get explicit permissions

$acl = Get-Acl -Path ADDOM:$DN
# Set inheritance to true
$acl.SetAccessRuleProtection($false,$false)
$acl.Access |
  # ...find all not inherited permissions.
  Where-Object { $_.isInherited -eq $false } |
  # ...and remove them
  ForEach-Object { $acl.RemoveAccessRule($_) } 

# set new permissions
$acl | Set-Acl -Path ADDOM:$DN

        
}


}
Remove-PSDrive ADDOM
}
Jacob Pagano
  • 15
  • 1
  • 7
  • But what's the problem then? Do you get errors or anything? – Kluk Aug 15 '20 at 17:07
  • Method invocation failed because [Microsoft.ActiveDirectory.Management.ADObject] does not contain a method named 'op_Addition'. At \\A1\ActiveDirectory\Script Development\takeOwnerAutomation.ps1:13 char:1 + $Identities = $Identities1 + $Identities2 + $Identities3 + $Identitie ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (op_Addition:String) [], RuntimeException + FullyQualifiedErrorId : MethodNotFound – Jacob Pagano Aug 15 '20 at 17:08
  • To combine multiple variables into an array you'll want `,`, not `+` - `$Identities = $Identities2,$Identities3,$Identities4,$Identities5` – Mathias R. Jessen Aug 15 '20 at 17:27
  • In my updated code above I honestly just ended up creating an if then statement for each identity. – Jacob Pagano Aug 15 '20 at 17:29
  • Now I have a new problem though. When I run the code as a domain admin, it works perfectly. But when I run it as a service account, on any object that the service account doesn't have "Modify Owner", it doesn't work. But it shouldn't need that because I gave the service account the rights to Take Ownership in the Group Policy. – Jacob Pagano Aug 15 '20 at 17:30
  • Is there something I have to write in the code to invoke those permissions? – Jacob Pagano Aug 15 '20 at 17:31
  • Did you target the DCs with the GPO that grants the privilege to the service account? – Mathias R. Jessen Aug 15 '20 at 17:47
  • Okay so I figured out the issue. I setup the GPO at the root of the domain, and the Default Domain Controllers Policy was taking precedence. I am testing a scheduled task now and we will see again. – Jacob Pagano Aug 15 '20 at 17:58
  • Btw, it appears to me that all of your efforts can be subverted if improper delegations already exist - your script doesn't do anything about the ACLs on OUs or Containers – Mathias R. Jessen Aug 15 '20 at 18:01
  • Well I don't have to worry about that because there is no admin with the ability to Change Permissions on OUs. The only people who can do that are Domain Admins which don't have an interest in doing so. – Jacob Pagano Aug 15 '20 at 18:06
  • This issue has a lot of unrelated details and shifted from the original problem. Please create a new [mcve] of the current issue. – iRon Aug 16 '20 at 07:29
  • @iRon Yes there were a lot of issues. Unfortunately with gMSA's, it is very hard to troubleshoot the problem because you can only use a gMSA with a Service or Scheduled Task and you can't see it run interactively. – Jacob Pagano Aug 16 '20 at 09:42
  • Sorry, I wasn't clear, what I meant is that you should create a new question with a [mcve], see also [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask). This way you would get better answers to you question and others might leverage from it also. Which regards to "*because you can only use a gMSA with a Service or Scheduled Task and you can't see it run interactively*", please see: [Scheduled Task Powershell Script - Runs OK as user account, but not as SYSTEM](https://stackoverflow.com/a/51612478/1701026) – iRon Aug 16 '20 at 10:52

1 Answers1

0

This is v001 of the code and so far I have had no issues. I will more than likely revisit this code and add in reporting via the ImportExcel Module but for now...

Try {
            [void][TokenAdjuster]
        } Catch {
            $AdjustTokenPrivileges = @"
            using System;
            using System.Runtime.InteropServices;

             public class TokenAdjuster
             {
              [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
              internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
              ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
              [DllImport("kernel32.dll", ExactSpelling = true)]
              internal static extern IntPtr GetCurrentProcess();
              [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
              internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr
              phtok);
              [DllImport("advapi32.dll", SetLastError = true)]
              internal static extern bool LookupPrivilegeValue(string host, string name,
              ref long pluid);
              [StructLayout(LayoutKind.Sequential, Pack = 1)]
              internal struct TokPriv1Luid
              {
               public int Count;
               public long Luid;
               public int Attr;
              }
              internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
              internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
              internal const int TOKEN_QUERY = 0x00000008;
              internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
              public static bool AddPrivilege(string privilege)
              {
               try
               {
                bool retVal;
                TokPriv1Luid tp;
                IntPtr hproc = GetCurrentProcess();
                IntPtr htok = IntPtr.Zero;
                retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
                tp.Count = 1;
                tp.Luid = 0;
                tp.Attr = SE_PRIVILEGE_ENABLED;
                retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
                retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
                return retVal;
               }
               catch (Exception ex)
               {
                throw ex;
               }
              }
              public static bool RemovePrivilege(string privilege)
              {
               try
               {
                bool retVal;
                TokPriv1Luid tp;
                IntPtr hproc = GetCurrentProcess();
                IntPtr htok = IntPtr.Zero;
                retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
                tp.Count = 1;
                tp.Luid = 0;
                tp.Attr = SE_PRIVILEGE_DISABLED;
                retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
                retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
                return retVal;
               }
               catch (Exception ex)
               {
                throw ex;
               }
              }
             }
"@
            Add-Type $AdjustTokenPrivileges
        }

        #Activate necessary admin privileges to make changes without NTFS perms
        [void][TokenAdjuster]::AddPrivilege("SeRestorePrivilege") #Necessary to set Owner Permissions
        [void][TokenAdjuster]::AddPrivilege("SeBackupPrivilege") #Necessary to bypass Traverse Checking
        [void][TokenAdjuster]::AddPrivilege("SeTakeOwnershipPrivilege") #Necessary to override FilePermissions




$NewOwner = (Get-ADServiceAccount SVC._DA001).samAccountName
$Domains = (Get-ADForest).Domains

ForEach($Domain in $Domains){

$Identities1 = Get-ADObject -Filter * -Server $Domain -Properties objectClass,CanonicalName | Where {$_.objectClass -eq $null}
$Identities2 = Get-ADComputer -Filter * -Properties samAccountName,memberOf,adminCount,CanonicalName,objectClass -Server $Domain | Where {$_.adminCount -lt 1}
$Identities3 = Get-ADGroup -Filter * -Properties samAccountName,memberOf,adminCount,CanonicalName,objectClass -Server $Domain | Where {$_.adminCount -lt 1}
$Identities4 = Get-ADServiceAccount -Filter * -Properties samAccountName,memberOf,adminCount,CanonicalName,objectClass -Server $Domain | Where {$_.adminCount -lt 1}
$Identities5 = Get-ADUser -Filter * -Properties samAccountName,memberOf,adminCount,CanonicalName,objectClass -Server $Domain | Where {$_.adminCount -lt 1}
$baseDN = (Get-ADDomain $Domain).DistinguishedName


$Server = (Get-ADDomainController -Server $Domain).name

Import-Module ActiveDirectory
New-PSDrive -Name ADDOM -PSProvider ActiveDirectory -Server $Domain -Scope Global -Root "//ROOTDSE/" | Out-Null


if (!($Identities1 -eq $null)){
foreach ($obj in $Identities1) {

  $DN = $obj.distinguishedName
  if (!($obj.memberOf -like "*Permissions Auditor Exemption*"))
  {
  Write-Host $DN
    #First Set the Owner to the SVC Account.
    $acl = get-acl -Path "ADDOM:CN=Users,$baseDN"
    $acl.SetOwner([Security.Principal.NTaccount]($NewOwner))
    set-acl -path ADDOM:$DN -AclObject $acl
    Start-Sleep -s 2



# get explicit permissions

$acl = Get-Acl -Path ADDOM:$DN
# Set inheritance to true
$acl.SetAccessRuleProtection($false,$false)
$acl.Access |
  # ...find all not inherited permissions.
  Where-Object { $_.isInherited -eq $false } |
  # ...and remove them
  ForEach-Object { $acl.RemoveAccessRule($_) } 

# set new permissions
$acl | Set-Acl -Path ADDOM:$DN

        
}


}

}

foreach ($obj in $Identities2) {

  $DN = $obj.distinguishedName
  if (!($obj.memberOf -like "*Permissions Auditor Exemption*"))
  {
  Write-Host $DN
    #First Set the Owner to the SVC Account.
    $acl = get-acl -Path ADDOM:$DN
    $acl.SetOwner([Security.Principal.NTaccount]($NewOwner))
    set-acl -path ADDOM:$DN -AclObject $acl
    Start-Sleep -s 2



# get explicit permissions

$acl = Get-Acl -Path ADDOM:$DN
# Set inheritance to true
$acl.SetAccessRuleProtection($false,$false)
$acl.Access |
  # ...find all not inherited permissions.
  Where-Object { $_.isInherited -eq $false } |
  # ...and remove them
  ForEach-Object { $acl.RemoveAccessRule($_) } 

# set new permissions
$acl | Set-Acl -Path ADDOM:$DN

        
}


}


foreach ($obj in $Identities3) {

  $DN = $obj.distinguishedName
  if (!($obj.memberOf -like "*Permissions Auditor Exemption*"))
  {
  Write-Host $DN
    #First Set the Owner to the SVC Account.
    $acl = get-acl -Path ADDOM:$DN
    $acl.SetOwner([Security.Principal.NTaccount]($NewOwner))
    set-acl -path ADDOM:$DN -AclObject $acl
    Start-Sleep -s 2



# get explicit permissions

$acl = Get-Acl -Path ADDOM:$DN
# Set inheritance to true
$acl.SetAccessRuleProtection($false,$false)
$acl.Access |
  # ...find all not inherited permissions.
  Where-Object { $_.isInherited -eq $false } |
  # ...and remove them
  ForEach-Object { $acl.RemoveAccessRule($_) } 

# set new permissions
$acl | Set-Acl -Path ADDOM:$DN

        
}


}


foreach ($obj in $Identities4) {

  $DN = $obj.distinguishedName
  if (!($obj.memberOf -like "*Permissions Auditor Exemption*"))
  {
  Write-Host $DN
    #First Set the Owner to the SVC Account.
    $acl = get-acl -Path ADDOM:$DN
    $acl.SetOwner([Security.Principal.NTaccount]($NewOwner))
    set-acl -path ADDOM:$DN -AclObject $acl
    Start-Sleep -s 2



# get explicit permissions

$acl = Get-Acl -Path ADDOM:$DN
# Set inheritance to true
$acl.SetAccessRuleProtection($false,$false)
$acl.Access |
  # ...find all not inherited permissions.
  Where-Object { $_.isInherited -eq $false } |
  # ...and remove them
  ForEach-Object { $acl.RemoveAccessRule($_) } 

# set new permissions
$acl | Set-Acl -Path ADDOM:$DN

        
}


}


foreach ($obj in $Identities5) {

  $DN = $obj.distinguishedName
  if (!($obj.memberOf -like "*Permissions Auditor Exemption*"))
  {
  Write-Host $DN
    #First Set the Owner to the SVC Account.
    $acl = get-acl -Path ADDOM:$DN
    $acl.SetOwner([Security.Principal.NTaccount]($NewOwner))
    set-acl -path ADDOM:$DN -AclObject $acl
    Start-Sleep -s 2



# get explicit permissions

$acl = Get-Acl -Path ADDOM:$DN
# Set inheritance to true
$acl.SetAccessRuleProtection($false,$false)
$acl.Access |
  # ...find all not inherited permissions.
  Where-Object { $_.isInherited -eq $false } |
  # ...and remove them
  ForEach-Object { $acl.RemoveAccessRule($_) } 

# set new permissions
$acl | Set-Acl -Path ADDOM:$DN

        
}


}



Remove-PSDrive ADDOM
}
Jacob Pagano
  • 15
  • 1
  • 7