Learning PowerShell a.k.a. “How to change 50 local admin passwords in 2 minutes”

When someone leaked a local administrator account password to roughly 50 web servers in our hosted environment my first reaction was @#$%*&^! because they’re not on a domain and I knew that meant I would be spending the next hour changing passwords. So, I decided that I can’t put it off anymore… I need to learn PowerShell. After reading the Intro paragraph of the dust-covered PowerShell book sitting on my desk and 45 minutes of scouring the web I was ready to go! The script prompts for the username who’s password you want to change, the new password, the username/password of the account logging in to actually make the change. It uses a list of servers called ServerList.txt (I didn’t incorporate any kind of AD query since this was used for non-domain servers). I’ve also included simple but informative screen output as well as some simple error checking and logging.

So without further delay here is my first PowerShell script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#************************************************************************************
#
# NAME: AdminPWreset.ps1
#
# AUTHOR: Allen Oliver
#
# EMAIL: admin@evilemuofdoom.com
#
# COMMENTS:
#   ***NOTE*** Requires Powershell 2.0! (I think... it's possible I might have fixed
#              this but I no longer have Powershell 1.0 installed anywhere to test)
#
#   This script takes entries in a text file called ServerList.txt and resets the
#   password to the specified local account (Administrator by default).  It also
#   provides a simple dated log file.
#
# SPECIAL THANKS!:
#   Thanks goes out to the numerous contributors at poshcode.com!
#   Since installing Windows 7 on my laptop I lost my reference links :(  If you
#   think your site contributed to this script, let me know so I can give proper
#   credit.
#   Thanks @octopauly for the "–assecurestring" parameter to mask PW!
#
# VERSION HISTORY:
# 1.0 - 7/28/2009 - Wrote and tested script
# 2.0 - 8/3/2009 - Added logging and comments
#
#************************************************************************************

cls
#Hide errors from console, set logfile name to PWChange-MM-DD-YYYY.log
$ErrorActionPreference = "SilentlyContinue"
$logFile = "PWChange-$((get-date).ToString('MM-dd-yyyy')).log"

#Prompt for Username who's PW will be changed
$UserName = Read-Host "Enter the local username who's password you want changed (Leave blank for Administrator)"

#If username is left blank, set to "Administrator"
If($UserName -match $null){ $UserName = "Administrator"}

#Prompt for new PW
$NewPW = Read-Host –assecurestring "Enter the new password"

#Get login credentials
$AdminUser = Read-Host "Please enter the username used to login to the servers (Leave blank for Administrator)"
If($AdminUser -match $null){ $AdminUser = "Administrator"}
$AdminPW = Read-Host –assecurestring "Enter Password"
cls

$Time = (Get-Date -format g)
Add-Content "$Time - Script started" -path $logFile -passthru

#Set pw for each server in ServerList.txt with simple error checking and logging.
foreach($Server in get-content ServerList.txt){
    $x = 0
    $myuser = new-Object System.DirectoryServices.DirectoryEntry("WinNT://$Server/$UserName,user",$AdminUser,$AdminPW)
    If($?){$x = $x + 1}
        Else{$x = 0}
    $myuser.psbase.invoke("SetPassword",$NewPW)
    If($?){$x = $x + 1}
        Else{$x = 0}
    $myuser.psbase.CommitChanges()
    If($?){$x = $x + 1}
        Else{$x = 0}
    $Time = (Get-Date -format g)
    If($x -eq 3){
            Add-Content "$Time - Password Reset was Successful for $Server" -path $logFile -passthru
            }
        Else{
            Write-Host "$Time - Password Reset FAILED for $Server" -ForegroundColor black -BackgroundColor red
            Add-Content "$Time - Password Reset FAILED for $Server" -path $logFile
            }
    }

$Time = (Get-Date -format g)
Add-Content "Completed on $Time. Results logged to $logFile" -path $logFile -passthru
Add-Content "-------------------------------------------------------------------------------" -path $logFile -passthru
Write-Host ""
Write-Host "Press any key to continue..."
$x = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

All in all I think it’s not bad for my first PowerShell script. It could be a little prettier or arranged in functions but it’ll do for now. It was a great learning experience that has led me into using PowerShell to perform administrative tasks in VMware, but that’s another post entirely ;) . Feedback, corrections, or suggestions are welcome.

Update: Thanks @octopauly for the following VERY helpful suggestion via Twitter :)

@evilemuofdoom By adding the –assecurestring parameter you can mask the data entered. Good practice with passwords. http://tr.im/vYC2

Leave a Comment