3

I'm trying to create a script for resetting local admin password for a remote computer in my organization. I'm pretty new to powershell, and I'm learning most of it by trying and failling in the process. The script I have so far:

Import-Module ActiveDirectory $computer = Read-Host -Prompt "Enter computer Name Here" $password = Read-Host -Prompt "Enter Password Here" Set-ADAccountPassword - Identity $computer -NewPassword $password 

Most likely it's just a stupid mistake, so please be gentle with me :)

5
  • If you really are setting the local admin password you need Set-LocalUser run on the remote computer instead of Set-ADAccountPassword. Also there musn't be a whitespace in -Identity. Commented Sep 4, 2018 at 11:57
  • If you change the password of a Computer account in the domain then it won't change the local Admin password on that Computer, but it changes the Computer's AD password (and probably breaking the trust between the Computer and the Domain Controller). Commented Sep 4, 2018 at 12:00
  • 1
    I'd recommend taking the time to implement LAPS (Local Admin Password Solution). It's free and works very well. Commented Sep 6, 2018 at 8:13
  • @twconnell LAPS is a good recommendation. Its use is complicated by the facts that it must be installed on all systems, requires schema extensions in AD, and is managed via GPO. Some environments (such as the one I work in) can lead to the business case that, especially for a one-time change to local passwords, the work to implement LAPS and train all the admins on its use is not worth it. For example, I seem to be cursed with always having at least one team member who can't understand GPOs. Commented Sep 6, 2018 at 15:59
  • Resetting admin passwords must occur often. The key reason to use LAPS is that it ensures a random password is set on every system. This is huge for preventing lateral movement from local admin credential theft situations. Most organizations will run a remote password reset script, but set the same password on every machine. This opens them up to pass the hash attacks which are fairly hard to detect or prevent when all your passwords are the same. So either set every system local admin password to be different and keep track of them, or let LAPS do it for you. Commented Sep 7, 2018 at 17:42

2 Answers 2

3

TL;DR

I agree with the other answer that the PowerShell ADSI adapter works for this. I also agree with the comments that if you want to interactively provide credentials, you should use Get-Credential and not Read-Host.


Here's how I did it - I think I grabbed this script from some web site and I'm embarrassed I can't give credit because I didn't comment or keep track of where I got it from.

Preparation

First, my script tests the connection:

if((Test-Connection -ComputerName $Computer -count 1 -ErrorAction 0)) { $Isonline = "ONLINE" Write-Verbose "`t$Computer is Online" } else { Write-Verbose "`t$Computer is OFFLINE" } 

The password change

Then my script uses try/catch to attempt to set the password and record and report success or failure:

try { $account = [ADSI]("WinNT://$Computer/-PUT THE USERNAME YOU WANT TO CHANGE HERE-,user") $account.psbase.invoke("setpassword",$password) Write-Verbose "`tPassword Change completed successfully" } catch { $status = "FAILED" Write-Verbose "`tFailed to Change the administrator password. Error: $_" } 

There are some differences here. First, I knew the username of the account I wanted to change in advance (my script was to change all the local admin passwords at once). You can use

$user = [adsi]"WinNT://$computer/$($credential.GetNetworkCredential().Username),user" 

instead as mentioned in the other answer. Also, my script (which worked for me on 2012 R2 servers) uses $user.psbase.invoke("setpassword",$password) instead of $user.SetPassword($password). I confess I don't know what the difference is or whether one will work better than the other.

Reporting

Finally, my script reports on success/failure. This is because I used my script to iterate through all of the servers in the environment to update all of the local admin passwords, so I needed to know which servers failed, if any, so I could manually go back and address them. This may not be necessary for you at all.

$obj = New-Object -TypeName PSObject -Property @{ ComputerName = $Computer IsOnline = $Isonline PasswordChangeStatus = $Status } $obj | Select ComputerName, IsOnline, PasswordChangeStatus if($Status -eq "FAILED" -or $Isonline -eq "OFFLINE") { $stream.writeline("$Computer `t $isonline `t $status") } 
1

If you have Powershell 5.0 or earlier then you need to use the Powershell ADSI adapter to manipulate a local user account on a remote computer:

$computer = Read-Host -Prompt "Enter Computer Name Here"; $credential = Get-Credential -UserName "Administrator" -Message "Enter new password"; $user = [adsi]"WinNT://$computer/$($credential.GetNetworkCredential().Username),user"; $user.SetPassword($credential.GetNetworkCredential().Password); $user.SetInfo(); 

You might want to check that you can ping the remote computer before actually trying to connect to it and handle that case when the user clicks Cancel on the credentials input dialog.

$computer = Read-Host -Prompt "Enter Computer Name Here"; If (Test-Connection -ComputerName $computer -Count 2 -Quiet) { Write-Host "The computer responded to our ping request. Connecting..."; $credential = Get-Credential -UserName "Administrator" -Message "Enter new password"; If ($credential -eq $null) { Write-Warning "The username and/or the password is empty! I quit."; Exit; } $user = [adsi]"WinNT://$computer/$($credential.GetNetworkCredential().Username),user"; $user.SetPassword($credential.GetNetworkCredential().Password); $user.SetInfo(); } Else { Write-Warning "The computer does not respond to our ping request. I quit."; } 

Edit: In Windows 10 build 1607 the new Powershell 5.1 introduced the Set-LocalUser command. You can use it for this task instead of the ADSI adapter but it requires the Powershell remoting service to be enabled (which is disabled by default) on the remote computers. To allow accepting remote commands you need to run run Enable-PSRemoting in an elevated Powershell terminal on the remote computer.

If PS remoting is enabled then a modified script is going to look like this:

$computer = Read-Host -Prompt "Enter Computer Name Here"; If (Test-Connection -ComputerName $computer -Count 2 -Quiet) { Write-Host "The computer responded to our ping request. Connecting..."; Invoke-Command -ComputerName $computer -ScriptBlock { $credential = Get-Credential -UserName "Administrator" -Message "Enter new password"; If ($credential -eq $null) { Write-Warning "The username and/or the password is empty! I quit."; Exit; } Set-LocalUser -Name $credential.UserName -Password $credential.Password; } } Else { Write-Warning "The computer does not respond to our ping request. I quit."; } 
1
  • 2
    Please update your example to use Get-Credential instead. Professional pwsh engineers avoid read-host like the plague. Commented Sep 4, 2018 at 17:53

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.