Comment un utilisateur Windows standard peut-il modifier son mot de passe à partir de la ligne de commande?

18

Sur Windows Server 2008 R2, j'ai un utilisateur local standard (non administrateur) (pas un compte Active Directory, bien que le serveur se trouve dans un domaine) qui a accès au serveur uniquement via PowerShell Remoting. L'utilisateur ne peut pas se connecter via RDP.

J'aimerais que cet utilisateur puisse changer son mot de passe. La commande 'net user' requiert des droits d'administrateur, même si l'utilisateur essaie de changer son propre mot de passe.

Comment un utilisateur standard peut-il changer son mot de passe à partir de la ligne de commande?

elijahbuck
la source

Réponses:

18

Voici du code PowerShell pour faire ce que vous cherchez avec des comptes de domaine:

param (
    [string]$oldPassword = $( Read-Host "Old password"),
    [string]$newPassword = $( Read-Host "New password")
)

$ADSystemInfo = New-Object -ComObject ADSystemInfo
$type = $ADSystemInfo.GetType()
$user = [ADSI] "LDAP://$($type.InvokeMember('UserName', 'GetProperty', $null, $ADSystemInfo, $null))"
$user.ChangePassword( $oldPassword, $newPassword)

Le fournisseur ASDI prend également en charge la syntaxe WinNT://computername/usernamede la ChangePassword()méthode. L' ADSystemInfoobjet, cependant, ne fonctionnera pas pour les comptes de la machine locale, de sorte que le code modernisation ci - dessus avec la WinNT://...syntaxe n'est pas réalisable.

(Quelqu'un veut-il suggérer une modification avec un code pour différencier les comptes locaux et les comptes de domaine?)

Sur une approche complètement différente, l'ancienne NetUserChangePasswordAPI fonctionnera également avec les comptes locaux (et de domaine, à condition que vous spécifiiez le nom de domaine dans la syntaxe NetBIOS):

param (
    [string]$oldPassword = $( Read-Host "Old password"),
    [string]$newPassword = $( Read-Host "New password")
)

$MethodDefinition = @'
[DllImport("netapi32.dll", CharSet = CharSet.Unicode)]
public static extern bool NetUserChangePassword(string domainname, string username, string oldPassword, string newPassword);
'@

$NetAPI32 = Add-Type -MemberDefinition $MethodDefinition -Name 'NetAPI32' -Namespace 'Win32' -PassThru

$NetAPI32::NetUserChangePassword('.', $env:username, $oldPassword, $newPassword)

Ce code suppose que vous modifiez un mot de passe sur la machine locale (".").

Evan Anderson
la source
1
Vous m'avez battu, mais je gagne pour la conservation des personnages;) Pour quelle raison savez-vous que les pièces supplémentaires que vous avez utilisées sont nécessaires? Ou tout simplement pour être plus formel et approprié?
charleswj81
1
Vous obtenez certainement le prix de golf de code. Je suis juste un peu formel et approprié ... En fait, cela rend principalement le script un peu plus utilisable par d'autres qui pourraient être de type copier-coller.
Evan Anderson
1
@ charleswj81 - La réponse d'Evan est bien plus complète. Il s'agit d'un PS1script autonome qui peut être appelé avec ou sans paramètres. C'est aussi beaucoup plus lisible. Le code est tout au sujet des humains comprenant ce que quelqu'un d'autre a écrit, pas l'ordinateur. Aucune des deux solutions ne sera plus rapide que l'autre.
Mark Henderson
1
Cela semble prometteur, mais je dois préciser que le compte est local au système. J'ai tenté ce qui suit: ([ADSI]'WinNT://localhost/USERNAME').ChangePassword("OLDPASS", "NEWPASS") Mais cela a retourné 'Le mot de passe ne répond pas aux exigences de la politique de mot de passe ...'. Le nouveau mot de passe répond cependant à ces exigences.
elijahbuck
1
En fait, après avoir ajouté l'utilisateur à «Utilisateurs du Bureau à distance» et tenté de changer le mot de passe de cette façon, j'obtiens la même erreur. Je crois que la bonne façon de changer un compte local est: ([ADSI]'WinNT://localhost/USERNAME').ChangePassword("OLDPASS", "NEWPASS")
elijahbuck
9

C'est en fait assez simple dans PowerShell:

([ADSI]'LDAP://CN=User,CN=Users,DC=domain').ChangePassword('currentpassword','newpassword')
charleswj81
la source
3

J'ai essayé les deux réponses ci-dessus en vain, pour changer le mot de passe d'un administrateur local qui n'est pas joint au domaine. En fouillant dans les commentaires, j'ai trouvé ce dont j'avais besoin.

Pour la deuxième partie de la réponse actuellement acceptée, vous souhaitez mettre à jour la signature à utiliser longau lieu de la boolvaleur de retour, et celles-ci peuvent être résolues dans la documentation des codes d'erreur système . Vous vous retrouvez donc avec:

param (
    [string]$oldPassword = $( Read-Host "Old password"),
    [string]$newPassword = $( Read-Host "New password")
)

$MethodDefinition = @'
[DllImport("netapi32.dll", CharSet = CharSet.Unicode)]
public static extern **long** NetUserChangePassword(string domainname, string username, string oldPassword, string newPassword);
'@

$NetAPI32 = Add-Type -MemberDefinition $MethodDefinition -Name 'NetAPI32' -Namespace 'Win32' -PassThru

$NetAPI32::NetUserChangePassword('.', $env:username, $oldPassword, $newPassword)

Cependant, cela n'a pas fonctionné pour moi. Les codes d'erreur ont alterné entre 86 et 2221, selon la façon dont j'ai configuré les paramètres. Était sur le point d'abandonner et de creuser davantage dans les commentaires, et a finalement réussi à faire:

([ADSI]'WinNT://./USERNAME').ChangePassword("OLDPASS‌​", "NEWPASS")

Absolument ridicule que le simple CHANGEMENT d'un mot de passe administrateur local est si compliqué dans Powershell. Si vous stockez des chaînes de sécurité sur votre système, la mise à jour du mot de passe doit être effectuée en fournissant l'ancien mot de passe, sinon vous risquez de perdre la capacité de décrypter correctement ces chaînes sécurisées!

gnalck
la source