Powershell Updating Local Admin Passwords Securely 3 of 3
Below is an example of how to remotely (using PowerShell) update and change the Local Administrator password securely. This is not my script, I received this script along with many others from the SANS SEC 505 course. I have not altered it in any way.
Updating the Passwords of the Local Administrator on remote mahcines (You must have a Certificate either from your CA or another Certificate Authority):
This script will remove older local administrator passwords that you have created with the first part (1 of 3) which is decrypted by your Private Key Certificate in (2 of 3).
Copy this text into a PowerShell Script called CleanUp_PasswordArchive.ps1
[code ]
#################################################################################### #.Synopsis
Carefully delete only the correct password archive files previously
created with the companion script named Update-PasswordArchive.ps1.
#.Description
Deletes older password archive files while retaining a chosen number
(default = 5) of prior successful and failed archive files for each
unique combination of computer and user (total of 10 files by default
for each unique combination). Scheduling this script will help to
maintain a reasonable number of password archive files.
#.Parameter PasswordArchivePath
The local or UNC path to where the encrypted password files are kept.
#.Parameter ComputerName
Name of the computer with the local account whose password was reset
and whose password was encrypted and saved to a file. The computer
name will match the names of files in the PasswordArchivePath. This
parameter can accept a computer name with a wildcard in it. When
specified, only the archives for that computer (or for those matching
computers with a wildcard) will be cleaned up instead of the default,
which is to clean up archive files for all computers.
#.Parameter ArchivesToKeep
The number of current and prior password archive files to keep for
each combination of computer name and user name. A single computer
might have multiple local user accounts whose passwords are managed
by these scripts, so the clean up must handle this gracefully. The
default is 5 (5 successful files + 5 failures files = 10 files).
#.Parameter VerboseReporting
Switch to show verbose information.
#.Parameter DoNotDelete
Switch to do a -WhatIf dry run that will not actually delete any
files. Use this switch along with -VerboseReporting for testing.
#.Parameter DeleteAllPasswordArchives
Switch to delete all password archive files without exception.
#.Example
.\CleanUp-PasswordArchive.ps1 -PasswordArchivePath \server\share
Deletes all but the last 5 password archive files for each computer
and user combination. Also, deletes all but the last 5 failure-type
files for each combination. Hence, if the last successful reset was
six months ago, followed by many failures, the last 5 successful
reset archive files will not be deleted.
#.Example
.\CleanUp-PasswordArchive.ps1 -PasswordArchivePath \server\share -ComputerName WKS*
Only cleans up the archive files for computers which match the "WKS*" file
pattern. A full computer name can be specified, wildcards are not required.
Regular expressions are not supported.
#.Example
.\CleanUp-PasswordArchive.ps1 -PasswordArchivePath \server\share -DoNotDelete -VerboseReporting
No files will be deleted, but a verbose report of files discovered will be shown.
#Requires -Version 2.0
#.Notes
Author: Jason Fossen, Enclave Consulting (http: //www.sans.org/windows-security/)
Version: 1.0
Updated: 11.Nov.2012
LEGAL: PUBLIC DOMAIN. SCRIPT PROVIDED "AS IS" WITH NO WARRANTIES OR GUARANTEES OF
ANY KIND, INCLUDING BUT NOT LIMITED TO MERCHANTABILITY AND/OR FITNESS FOR
A PARTICULAR PURPOSE. ALL RISKS OF DAMAGE REMAINS WITH THE USER, EVEN IF
THE AUTHOR, SUPPLIER OR DISTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF
ANY SUCH DAMAGE. IF YOUR STATE DOES NOT PERMIT THE COMPLETE LIMITATION OF
LIABILITY, THEN DELETE THIS FILE SINCE YOU ARE NOW PROHIBITED TO HAVE IT.
#################################################################################### Param ($PasswordArchivePath = ".", $ComputerName = "*", $ArchivesToKeep = 5, [Switch ] $VerboseReporting, [Switch ] $DoNotDelete, [Switch ] $DeleteAllPasswordArchives)
Test access to path.
if (Resolve-Path -Path $PasswordArchivePath)
{ $PasswordArchivePath = $(Resolve-Path -Path $PasswordArchivePath).Path
}
else
{ "nERROR: Cannot resolve path to archive folder: $PasswordArchivePath
n" ; exit
}
Sanity check on $ArchivesToKeep
if ($ArchivesToKeep -le 0) { "nERROR: The -ArchivesToKeep argument must be 1 or larger.
n" ; exit
}
Get all matching files.
$filter = $($ComputerName + "+++").Replace("**","*")
$files = dir -Path $PasswordArchivePath -Filter $filter
if ($VerboseReporting)
{
"nTotal number of matching ($ComputerName) archive files = " + $files.count $files | foreach { $_.fullname } "
n"
}
Maybe just delete them all.
if ($DeleteAllPasswordArchives -and $DoNotDelete) { "nERROR: Invalid combination of switches.
n" ; exit
}
if ($DeleteAllPasswordArchives -and $ComputerName -ne "*") { "nERROR: Invalid combination of switches.
n" ; exit
}
if ($DeleteAllPasswordArchives)
{
"nDeleting all password archive files...
n"
$files | foreach { remove-item $_
}
exit
}
Separate successful vs. failed password reset files.
$failurefiles = $files | where { $.Name -like "*FAILURE" } $successfiles = $files | where { $.Name -notlike "*FAILURE" } if ($VerboseReporting) { "Files for failed resets = " + $failurefiles.count } if ($VerboseReporting) { "Files for successful resets = " + $successfiles.count }
Build arrays of unique computername+username combinations.
$failurenames = @() $successnames = @()
foreach ($file in $failurefiles)
{
$computer = $($file.name -split ‘+’)[
0
] + "+" + $($file.name -split ‘+’)[
1
]
if ($computer -notin $failurenames){ $failurenames += $computer
}
}
if ($VerboseReporting) { "nUnique Computer+User combinations for failed resets = " + $failurenames.count } if ($VerboseReporting) { $failurenames ; "
n"
}
foreach ($file in $successfiles) { $computer = $($file.name -split ‘+’)[ 0 ] + "+" + $($file.name -split ‘+’)[ 1 ] if ($computer -notin $successnames){ $successnames += $computer } } if ($VerboseReporting) { "Unique Computer+User combinations for successful resets = " + $successnames.count } if ($VerboseReporting) { $successnames ; "`n" }
Delete the non-keepers for each unique name.
$SuccessFileCounter = $FailureFileCounter = 0
foreach ($name in $failurenames) { $targets = $failurefiles | where { $.Name -like ($name + "+*") } | sort Name if ($targets.count -le $ArchivesToKeep) { continue } 0..$($targets.count - $ArchivesToKeep - 1) | foreach { if (-not $DoNotDelete){remove-item $targets[$ ].fullname ; if($?){$FailureFileCounter++ } } } }
foreach ($name in $successnames) { $targets = $successfiles | where { $.Name -like ($name + "+*") } | sort Name if ($targets.count -le $ArchivesToKeep) { continue } 0..$($targets.count - $ArchivesToKeep - 1) | foreach { if (-not $DoNotDelete){remove-item $targets[$ ].fullname ; if($?){$SuccessFileCounter++ } } } }
Default Report
[String ] $SuccessFileCounter + " files deleted out of the set of " + [String ] $successfiles.count + " successful reset files." [String ] $FailureFileCounter + " files deleted out of the set of " + [String ] $failurefiles.count + " failure reset files." "`n"
[/code ]