Group Policy Preferences and Password Change
When Group Policy Preferences were introduced (my description in the article Group Policy Preferences, GPO, GPMC, GPME), they included an interesting option for controlling local user accounts, including changing passwords. Unfortunately, after a few years, Microsoft found that the stored password in this policy was not secure. Instead of solving the situation, they blocked the storage of passwords (CPassword attribute) and thus many options including password change. The official recommendation is to use some central script that remotely changes passwords. The problem description is in MS14-025: Vulnerability in Group Policy Preferences could allow elevation of privilege: May 13, 2014.
Using the Net user Command for User Management
Locally on the computer, we can use the command line tool net user, description Net user is a command. It offers a wide range of options.
We can set (change) the password:
net user user password
But also a number of other things, such as creating an account, disabling, setting account expiration.
net user /add user password net user user /ACTIVE:NO net user user /expire:Never net user user /expire:1.10.2016
We can work not only with local, but also with domain accounts. Example of getting information about a domain account:
net user user /domain
If we wanted to rename an account, we would have to use a different command:
wmic useraccount where name=currentname rename newname
These are calls that we can make locally. But if we remotely connect to a computer (e.g. using a PowerShell session), we can also use these commands (call local commands remotely).
PsPassword Tool for Remote Password Change
The PsPasswd application (PsPasswd - TechNet) from the popular Windows Sysinternals group provides a convenient way to remotely change passwords. Example of changing a password if running as a user who has permissions to the remote station:
pspasswd \\computer user password
Using PowerShell for Account Management
Unfortunately, PowerShell itself does not have any commands for managing local user accounts and passwords. But we can use the ADSI adapter and .NET classes and thus use the (somewhat more programming-oriented) wide range of control options.
We always start by creating a representation of the object, where we specify where and to what type we are connecting. For example, the User on the Station computer:
$user = [adsi]"WinNT://station/administrator, user"
Then we use the various methods and properties of the object. For example, the SetPassword method to set the password:
$user.SetPassword("Password")
Sometimes we can make the call directly, as shown above. Sometimes we need to use a slightly more complex notation:
$user.psbase.Invoke("SetPassword", "Password")
Examples of Operations on User Accounts Using PowerShell ADSI Adapter
Renaming the administrator user to admin on the station computer.
$user = [adsi]"WinNT://station/administrator, user"
$user.Rename("admin")
Changing the password of the admin user on the station computer.
$user = [adsi]"WinNT://station/admin, user"
$user.SetPassword("Password")
Disabling the admin account on the station computer.
$user = [adsi]"WinNT://station/admin, user" $user.AccountDisabled = $true $user.SetInfo()
Creating the admin account on the station computer.
$comp = [adsi]"WinNT://station"
$user = $comp.Create("User", "Admin")
$user.SetPassword("password")
$user.SetInfo()
Deleting the admin account on the station computer.
$comp = [adsi]"WinNT://station"
$comp.Delete("User", "Admin")
Adding the admin user to the local Administrators group on the station computer.
$user = [adsi]"WinNT://station/admin, user" $group = [adsi]"WinNT://station/Administrators, group" $group.Add($user.path)
List of local users on the station computer.
$users = ([adsi]"WinNT://$computer").Children | where {$_.SchemaClassName -eq 'user'}
$users.Name
List of members of the Administrators group on the station computer.
$group = [adsi]"WinNT://station/Administrators, group"
$group.psbase.invoke("members") | ForEach { $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null) }
Is the Admin user a member of the Administrators group on the station computer?
$group = [adsi]"WinNT://station/Administrators, group"
$isMember = $false
$group.psbase.invoke("members") | ForEach { if(($_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)).Equals("Admin")) { $isMember = $true; } }
$isMember
Changing a User Password on a Group of Remote Computers
Using PowerShell, we can make any bulk change. For example, we can save a list of computer names to a text file (one name per line), read it, and call in a loop. Or with some more secure password entry, so it's not stored in the script.
$username = "Emil"
$passwd = "Password"
$computers = Get-Content -path C:\computers.txt
Foreach($computer in $computers) {
$user = [adsi]"WinNT://$computer/$username, user"
$user.SetPassword($passwd)
}
Similarly, we can take a list of computers from a container in Active Directory, which is even more convenient.
$username = "Emil"
$passwd = "Password"
$OU = "OU=Computers,DC=company,DC=local"
Get-ADComputer -Filter * -SearchBase $OU |
ForEach-Object {
$computer = $_.Name
if(Test-Connection -ComputerName $_.Name -Count 1 -Quiet) {
"Changing password on computer " + $computer + " for user " + $username
$user = [adsi]"WinNT://$_.Name/$username, user"
$user.SetPassword($passwd)
}
}
We can play around with the script and improve it (perform various checks, respond to errors, perform more operations than just changing the password, etc.). Here I'll just add a note that we can save the output to a file. One option is to add the following to the beginning of the script:
Start-Transcript -path C:\output.txt
And at the end.
Stop-Transcript
Díky za pěkný článek.
U toho PsPassword je bohužel škoda že v poslední verzi 1.23 (staré několik let) je nějaký bug a nefungují korektně přepínače -u a -p což činí tento příkaz nepoužitelným (na místo vykonání příkazu se zobrazí pouze výpis syntaxe).
Předchozí verze 1.22 funguje korektně ale bohužel se nedá stáhnout z oficiálních stránek a stahovat ji jinde je potenciálně nebezpečné... mimochodem nemáte ji někdo nebo alespoň hash pro ověření pravosti?
Používáte někdo tento způsob změny hesla (PsPasswd) v ostrém prostředí?
Zdravicko, chcem len poukazat na super riesenie priamo od Microsoftu s nazvom LAPS (Local Administrator Password Management). Je celkom zaujimava novinka, ale osobne nemam skusenosti s nasadenim. Kedze kazdenmu pc generuje ine a nahodne heslo, plus sa pravidelne meni je to podla mna minimalne o uroven lepsie riesenie :)
respond to [2]Michal_F: když mi dátě na vás email tak vám pošlu dokumentaci, podle které jsem toto řešení před víc jak rokem nasazoval u nás :-)
tohle je docela funkční LAPS https://technet.microsoft.com/en-us/mt227395.aspx