Tuesday, February 25, 2014

Variations on a theme

That last script I posted wasn't exactly what I needed.  I had to rewrite it to leave existing permissions in-tact.  The one below accomplishes the same goal without deleting all existing ACLs.  There are a few assumptions in place.  First that the local admins group will be given full control to anything we touch.  Second, the TrustedInstaller account will be given full control, even if it only had read access before.  This just makes life easier.  I also fixed the logging so that everything is logged, just in case.  The application of the new ACLs is done individually instead of via a function so that things can be better customized.

There is a reference section at the bottom that lists some permissions options available.  It's not needed by the script.

I tested this script against my PC and a few test PCs.  There don't appear to be any ill effects.  Again, use at your own risk and watch for line wrapping.


#============================================================================
#         File Name : EditRemotePermissions.ps1
#   Original Author : Kenneth C. Mazie (kcmjr AT kcmjr.com)
#                   :
#       Description : Used to adjust insecure file permissions on remote
#                   : systems.
#                   :
#             Notes : Normal operation is with no command line options.
#                   :
#          Warnings :
#                   : 
#             Legal : Public Domain. Modify and redistribute freely. No
#                   : rights reserved.
#                   : SCRIPT PROVIDED "AS IS" WITHOUT WARRANTIES OR
#                   : GUARANTEES OF ANY KIND. USE AT YOUR OWN RISK. NO
#                   : TECHNICAL SUPPORT PROVIDED.
#                   :
#           Credits : Code snippets and/or ideas came from many sources
#                   : including but not limited to the following:
#                   :
#    Last Update by : Kenneth C. Mazie
#   Version History : v1.0 - 02-19-14 - Original
#    Change History : v2.0 - 02-25-14 -   
#                   :
#===========================================================================

Clear-Host
$Debug = $True
$ErrorActionPreference = "SilentlyContinue"
$BadUsers = @("Everyone","Domain Users","Authenticated Users","Users")
$TargetList = Get-Content c:\Scripts\TargetList.txt
$PathList = Get-Content c:\scripts\PathList.txt

#$TargetList = "testbox"
#$PathList = "c:\test\new text document.txt"

If (!(Test-Path "C:\Scripts\Logs")){New-Item -Path "c:\Scripts\Logs" -ItemType directory}

Function WriteLog
{
   Param ([string]$LogString)
   Add-content $LogFile -value $LogString
   If ($Debug){Write-Host $LogString}
}

function Run-RemoteCMD {
    param(
    [Parameter(Mandatory=$true,valuefrompipeline=$true)]
    [string]$computer,
    [string]$command
    )
    begin {
        [string]$cmd = "CMD.EXE /C " +$command
          }
    process {
        $newproc = Invoke-WmiMethod -class Win32_process -name Create -ArgumentList ($cmd) -ComputerName $computer #-WhatIf
        sleep -Seconds 1
        if ($newproc.ReturnValue -eq 0 ){
            WriteLog "Command $($command) invoked Sucessfully on $($computer)"
            } #--[ if command is sucessfully invoked it doesn't mean that it did what its supposed to do it means that the command only sucessfully ran on the cmd.exe of the server ]--
        }
    }

ForEach ($Target in $TargetList){                                               #--[ Cycle through target PCs ]--
  $LogFile = "c:\scripts\logs\$Target {0:MM-dd-yyyy_HHmm}.log" -f (Get-Date)
  If (Test-Connection -ComputerName $Target){
    ForEach ($File in $PathList){
      WriteLog "--[ Target File: ]----------------------------------`n$File"
      [string]$Drive = ($File.split(":"))[0]
      [string]$File = ($File.split(":"))[1]
      $Drive = $Drive + "$"
      $CurrentTarget = "\\$Target\$Drive$File"
      If (Test-Path -Path $CurrentTarget){
        $ACL = Get-ACL $CurrentTarget                                           #--[ Record current ACL ]--
        #$ACL | format-List
        $Owner = Out-String -InputObject $ACL.Owner
        $str = (@($ACL.Accesstostring) -split '[\r\n]')
        $count =  0
        WriteLog "`n--[ Pre-existing Owner: ]---------------------------`n$Owner`n--[ Pre-existing Permissions:]----------------------"
        while ($count -lt $str.count ){
          WriteLog $str[$count]
          ++ $count
        }
        WriteLog "`n--[ Taking ownership of target file: ]--------------"
        Run-RemoteCMD $Target "takeown /f $CurrentTarget /a "                   #--[ Call remote file takeover function ]--
        $str = ,$File + $str
        $out = $File
        $count =  0
        while ($count -lt $str.count ){
          $out = $out + $str[$count] + "+"
          $ACL.SetAccessRuleProtection($True, $False)

          if ($str[$count] | Select-string "TrustedInstaller"){
            $ACE = New-Object System.Security.AccessControl.FileSystemAccessRule @('NT SERVICE\TrustedInstaller', "FullControl",  'none','none','Allow')
            $ACL.AddAccessRule($ACE)
          }
        
          if ($str[$count] | Select-string "SYSTEM"){
            $ACE = New-Object System.Security.AccessControl.FileSystemAccessRule @('NT AUTHORITY\SYSTEM', "FullControl", 'none','none','Allow')
            $ACL.AddAccessRule($ACE)
          }
                
          if ($str[$count] | Select-string "Everyone"){
            $User = New-Object System.Security.Principal.NTAccount("Everyone")
            $ACE = New-Object System.Security.AccessControl.FileSystemAccessRule @('Everyone', 'FullControl, Write, Modify', 'none','none','Allow')
            $ACL.RemoveAccessRule($ACE)
            $ACE = New-Object System.Security.AccessControl.FileSystemAccessRule @('Everyone', "ReadAndExecute, Synchronize",  'none','none','Allow')
            $ACL.AddAccessRule($ACE)
          }
  
          if ($str[$count] | Select-string "BUILTIN\\Users"){
            $ACE = New-Object System.Security.AccessControl.FileSystemAccessRule @('Users', 'FullControl, Write, Modify', 'none','none','Allow')
            $ACL.RemoveAccessRule($ACE)  
            $ACE = New-Object System.Security.AccessControl.FileSystemAccessRule @("Users", "ReadAndExecute, Synchronize", 'none','none','Allow')
            $ACL.AddAccessRule($ACE)
          }
  
          if ($str[$count] | Select-string "Domain Users"){
            $ACE = New-Object System.Security.AccessControl.FileSystemAccessRule("Domain Users",  'FullControl, Write, Modify', 'none','none','Allow')
            $ACL.RemoveAccessRule($ACE)
            $ACE = New-Object System.Security.AccessControl.FileSystemAccessRule("Domain Users", "ReadAndExecute, Synchronize",  'none','none','Allow')
            $ACL.AddAccessRule($ACE)
          }
      
          if ($str[$count] | Select-string "Authenticated Users"){
            $ACE = New-Object System.Security.AccessControl.FileSystemAccessRule @('Authenticated Users', 'FullControl, Write, Modify', 'none','none','Allow')
            $ACL.RemoveAccessRule($ACE)  
            $ACE = New-Object System.Security.AccessControl.FileSystemAccessRule("Authenticated Users","ReadAndExecute, Synchronize",  'none','none','Allow')
            $ACL.AddAccessRule($ACE)
          }
          ++ $count
        }  
        #--[ Assign Local Administrator the Full Control right ]--
        WriteLog "`n"
        $ACE = New-Object System.Security.AccessControl.FileSystemAccessRule("BUILTIN\Administrators", "FullControl", 'none','none','Allow')
        $ACL.AddAccessRule($ACE)
  
        #--[ Apply the new ACL ]--
        Set-Acl $CurrentTarget $ACL #-WhatIf
      
        # --[ Read ACL again to detect changed rights ]--
        $ACL = Get-ACL $CurrentTarget
        $Owner = Out-String -InputObject $ACL.Owner
        $str = (@($ACL.Accesstostring) -split '[\r\n]') 
        $count =  0
        WriteLog "--[ Final Owner: ]----------------------------------`n$Owner`n--[ Final Permissions: ]----------------------------"
        while ($count -lt $str.count ){
          WriteLog $str[$count]
          ++ $count
        }
  
        $ACL = ""
        $ACE = ""

      }Else{
        WriteLog " --- FILE NOT FOUND ---"
      }
      WriteLog "`n================================================================`n"
    }
  }Else{
    WriteLog "================================================================`nNoConnection to $Target`n================================================================`n"
  }
}
WriteLog "`n--[ COMPLETED... ]-----------------------------------`n"


<#

REFERENCE:

  $Access = [System.Security.AccessControl.AccessControlType]::Allow
  $Rights = [System.Security.AccessControl.FileSystemRights]::"ReadAndExecute, Synchronize"
  $Inheritance = [System.Security.AccessControl.FileSystemAccessRule]::ContainerInherit -bor [System.Security.AccessControl.FileSystemAccessRule]::ObjectInherit
  $Propagation = [System.Security.AccessControl.PropagationFlags]::None


rights:

    AppendData
    ChangePermissions
    CreateDirectories
    CreateFiles
    Delete
    DeleteSubdirectoriesAndFiles
    ExecuteFile
    FullControl
    ListDirectory
    Modify
    Read
    ReadAndExecute
    ReadAttributes
    ReadData
    ReadExtendedAttributes
    ReadPermissions
    Synchronize
    TakeOwnership
    Traverse
    Write
    WriteAttributes
    WriteData
    WriteExtendedAttributes

InheritanceFlag to any of the following:

    ContainerInherit (the ACE is inherited by child containers, like subfolders)
    ObjectInherit (the ACE is inherited by child objects, like files)
    None

PropagtionFlag to any of these options:

    InheritOnly (the ACE is propagated to all child objects)
    NoPropagateInherit (the ACE is not propagated to child objects)
    None
#>