Lets Automate It

from Josh Rickard

Powershell Updating Local Admin Passwords Securely 3 of 3

2018-08-07 Josh Rickard

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 ]