¿Cómo puede un usuario estándar de Windows cambiar su contraseña desde la línea de comandos?

18

En Windows Server 2008 R2, tengo un usuario local estándar (no administrador) (no una cuenta de Active Directory, aunque el servidor está en un dominio) que tiene acceso al servidor solo a través de PowerShell Remoting. El usuario no puede iniciar sesión a través de RDP.

Me gustaría que este usuario pueda cambiar su contraseña. El comando 'usuario neto' requiere derechos de administrador, incluso si el usuario está tratando de cambiar su propia contraseña.

¿Cómo puede un usuario estándar cambiar su contraseña desde la línea de comandos?

elijahbuck
fuente

Respuestas:

18

Aquí hay un código de PowerShell para hacer lo que está buscando con las cuentas de dominio:

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)

El proveedor ASDI también admite la sintaxis WinNT://computername/usernamepara el ChangePassword()método. El ADSystemInfoobjetivo, sin embargo, no funcionará para las cuentas de equipo local, por lo que sólo reequipamiento el código anterior con la WinNT://...sintaxis no es viable.

(¿Alguien quiere sugerir una edición con código para diferenciar entre cuentas locales y de dominio?)

En una táctica completamente diferente, la antigua NetUserChangePasswordAPI también funcionará con cuentas locales (y de dominio, siempre que especifique el nombre de dominio en la sintaxis de 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)

Este código supone que está cambiando una contraseña en la máquina local (".").

Evan Anderson
fuente
1
Me ganaste, pero gano por la conservación de los personajes;) ¿Alguna razón por la que sabes que las partes adicionales que usaste son necesarias? ¿O simplemente para ser más formal y adecuado?
charleswj81
1
Definitivamente obtienes el código de premio de golf. Solo soy formal y apropiado ... En realidad, principalmente hace que el guión sea un poco más útil para otros que podrían ser tipos de cortar y pegar.
Evan Anderson
1
@ charleswj81 - La respuesta de Evan es mucho más completa. Es un PS1script independiente que se puede invocar con o sin parámetros. También es mucho más legible. El código se trata de que los humanos entiendan lo que alguien más ha escrito, no la computadora. Ninguna de las soluciones será más rápida que la otra.
Mark Henderson
1
Esto parece prometedor, pero debo aclarar que la cuenta es local para el sistema. Intenté lo siguiente: ([ADSI]'WinNT://localhost/USERNAME').ChangePassword("OLDPASS", "NEWPASS") Pero eso devolvió 'La contraseña no cumple con los requisitos de la política de contraseña ...'. Sin embargo, la nueva contraseña cumple con esos requisitos.
elijahbuck
1
En realidad, después de agregar al usuario a 'Usuarios de escritorio remoto' e intentar cambiar la contraseña de esa manera, obtengo el mismo error. Creo que la forma correcta de cambiar una cuenta local es: ([ADSI]'WinNT://localhost/USERNAME').ChangePassword("OLDPASS", "NEWPASS")
elijahbuck
9

Esto es realmente bastante simple en PowerShell:

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

Intenté ambas respuestas anteriores en vano, para cambiar la contraseña de un administrador local que no está unido al dominio. Sin embargo, hurgar en los comentarios arrojó lo que necesitaba.

Para la segunda parte de la respuesta actualmente aceptada, desea actualizar la firma para usar en longlugar del boolvalor de retorno, y estos pueden solucionarse en los documentos de códigos de error del sistema . Entonces terminas con:

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)

Sin embargo, eso no funcionó para mí. Los códigos de error alternaban entre 86 y 2221, dependiendo de cómo configuré los parámetros. Estaba a punto de rendirme y profundizar más en los comentarios, y finalmente encontré éxito al hacer:

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

Absolutamente ridículo que el CAMBIO simple de una contraseña de administrador local sea tan complicado en Powershell. Si almacena cadenas de seguridad en su sistema, entonces la actualización de la contraseña debe hacerse con el suministro de la contraseña anterior, ¡o corre el riesgo de perder la capacidad de descifrar esas cadenas seguras correctamente!

gnalck
fuente