We use a forensics tool to internally scan our network for vulnerabilities on a regular basis. This tool spits out a list of all sorts of stuff which we then go and address. One of the largest lists it gives us is insecure file permissions on Windows systems.
I wrote this script to address the issues. One problem I faced was that the files are largely owned by the "TrustedInstaller" account. You cannot easily adjust the permissions if that account has ownership so you need to change the ownership.
The script uses two flat text files as input. The first is just a list of target systems, one per line. The second is a list of files to adjust. Complete local paths are assumed. The script adjusts the paths from a local path to a remote path. It generates basic log files, one per target in the C:\Scripts\Logs folder. I decided on one per target since there was a lot of info in each.
The script first checks if the target is reachable. It then cycles through the files, checking if each exists. It then invokes a remote copy of TAKEOWN to take ownership of the file. Once that's done the permissions are edited, local admins is added, and TrustedInstaller is reapplied as owner.
NOTE: I set -whatif statements on the three lines that do the actual work. Remove or comment them out before you actually run the script.
Hopefully someone will get use out of it.
!!! WARNING !!! Don't blame me...you've been warned... This script can cause catastrophic corruption of Windows. If you reset the wrong permission on system files Windows WILL NOT BOOT. We ran into this on our test run. Test systems booted to a black screen after displaying the Windows flag. To repair it we booted to a live Windows CD, then ran "icacls * /t /c /q /reset" from the "c:\windows" folder. The command recursively replaces all inherited permissions on all files. After that the system booted normally.
Watch for word wrapping below.....
#======================================================================================
# 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 : v1.1 - 00-00-00 -
# :
#=======================================================================================
Clear-Host
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 ){
Write-Output "`nCommand
$($command) invoked Sucessfully on $($computer)`n"
Add-Content $LogFile "----------------------------------------------------------------`nCommand
$($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. syntax errors can
occur due to user input
}
}
$Debug = $true #--[ Set to $false to quiet local output
]--
$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" #--[ Use for
testing ]--
#$PathList = "c:\test\new
text document.txt" #--[ Use for
testing ]--
ForEach ($Target in $TargetList){
$LogFile = "c:\scripts\logs\$Target-{0:MM-dd-yyyy_HHmm}.log" -f (Get-Date)
If (Test-Connection -ComputerName $Target){
ForEach ($File in $PathList){
[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
If ($Debug){$ACL | format-List}
Run-RemoteCMD $Target "takeown
/f $CurrentTarget /a "
#$ACL.Access |
%{$acl.RemoveAccessRule($_)} #--[
Removes all access rules. DONT USE
$ACL.SetAccessRuleProtection($True, $False)
$Rights = [System.Security.AccessControl.FileSystemRights]::FullControl
$Inheritance = [System.Security.AccessControl.FileSystemAccessRule]::ContainerInherit
-bor [System.Security.AccessControl.FileSystemAccessRule]::ObjectInherit
$Propagation = [System.Security.AccessControl.PropagationFlags]::None
$Access = [System.Security.AccessControl.AccessControlType]::Allow
$ACE = New-Object System.Security.AccessControl.FileSystemAccessRule("BUILTIN\Administrators", $Rights, $Inheritance, $Propagation, $Access)
$ACL.AddAccessRule($ACE)
ForEach ($BadUser in $BadUsers){
$ACE = New-Object System.Security.AccessControl.FileSystemAccessRule($BadUser, $Rights, $Inheritance, $Propagation, $Access)
$ACL.RemoveAccessRule($ACE)
}
Set-Acl $CurrentTarget $ACL -WhatIf
$NewOwner=New-Object System.Security.Principal.NTAccount("NT
SERVICE\TrustedInstaller")
$ACL.SetOwner($NewOwner)
Set-Acl $CurrentTarget $ACL -WhatIf
$ACL = ""
$ACE = ""
$ACL = Get-ACL $CurrentTarget
Add-Content $LogFile "PREMISSIONS
ADJUSTED - $CurrentTarget"
If ($Debug){$ACL | Format-List}
Add-Content $LogFile "----------------------------------------------------------------"
If ($Debug){Write-Host "----------------------------------------------------------------"`n}
}Else{
If ($Debug){Write-Host "NOT FOUND
- $CurrentTarget"}
Add-Content $LogFile "NOT FOUND
- $CurrentTarget"
}
}
}Else{
Add-Content $LogFile "----------------------------------------------------------------`nNoConnection
to
$Target`n----------------------------------------------------------------`n"
Write-Host "----------------------------------------------------------------`nNoConnection
to
$Target`n----------------------------------------------------------------`n"
}
}
Write-Host
"Completed...." -ForegroundColor
Red