ผู้ใช้ Windows มาตรฐานสามารถเปลี่ยนรหัสผ่านจากบรรทัดคำสั่งได้อย่างไร


18

บน Windows Server 2008 R2 ฉันมีผู้ใช้ภายใน (ไม่ใช่ผู้ดูแลระบบ) มาตรฐาน (ไม่ใช่บัญชี Active Directory แม้ว่าเซิร์ฟเวอร์อยู่ในโดเมน) ที่สามารถเข้าถึงเซิร์ฟเวอร์ผ่าน PowerShell Remoting เท่านั้น ผู้ใช้ไม่สามารถเข้าสู่ระบบผ่าน RDP

ฉันต้องการให้ผู้ใช้รายนี้สามารถเปลี่ยนรหัสผ่านของพวกเขาได้ คำสั่ง 'ผู้ใช้เน็ต' ต้องการสิทธิ์ผู้ดูแลระบบแม้ว่าผู้ใช้พยายามเปลี่ยนรหัสผ่านของตนเอง

ผู้ใช้มาตรฐานสามารถเปลี่ยนรหัสผ่านจากบรรทัดคำสั่งได้อย่างไร

คำตอบ:


18

ต่อไปนี้เป็นรหัส PowerShell เพื่อทำสิ่งที่คุณต้องการด้วยบัญชีโดเมน:

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)

ผู้ให้บริการ ASDI ยังสนับสนุนไวยากรณ์WinNT://computername/usernameสำหรับChangePassword()วิธีการ อย่างไรก็ตามADSystemInfoวัตถุจะไม่ทำงานสำหรับบัญชีภายในเครื่องดังนั้นเพียงแค่การดัดแปลงรหัสข้างต้นด้วยWinNT://...ไวยากรณ์ไม่สามารถใช้งานได้

(ใครต้องการแนะนำการแก้ไขด้วยรหัสเพื่อแยกความแตกต่างระหว่างบัญชีท้องถิ่นและโดเมน?)

ในแทคที่แตกต่างกันโดยสิ้นเชิงNetUserChangePasswordAPI เก่าจะทำงานกับบัญชีโลคัล (และโดเมนหากคุณระบุชื่อโดเมนในไวยากรณ์ 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)

รหัสนี้จะถือว่าคุณเปลี่ยนรหัสผ่านในเครื่องท้องถิ่น (".")


1
คุณเอาชนะฉันไปได้ แต่ฉันชนะเพื่อการอนุรักษ์ตัวละคร;) ด้วยเหตุผลใดก็ตามที่คุณรู้ว่าชิ้นส่วนพิเศษที่คุณใช้มีความจำเป็น? หรือเพียงเพื่อจะเป็นทางการและเหมาะสมมากขึ้น?
charleswj81

1
คุณจะได้รับรางวัลโค้ดกอล์ฟอย่างแน่นอน ฉันแค่เป็นทางการและเหมาะสม ... จริง ๆ แล้วมันทำให้สคริปต์ใช้งานได้ง่ายขึ้นกับคนอื่น ๆ ที่อาจเป็นประเภทที่ถูกตัดและวาง
Evan Anderson

1
@ charleswj81 - คำตอบของ Evan นั้นสมบูรณ์กว่า เป็นPS1สคริปต์แบบสแตนด์อโลนที่สามารถเรียกใช้โดยมีหรือไม่มีพารามิเตอร์ มันอ่านได้มากขึ้นเช่นกัน รหัสคือทั้งหมดที่เกี่ยวกับมนุษย์ที่เข้าใจสิ่งที่คนอื่นเขียนไม่ใช่คอมพิวเตอร์ การแก้ปัญหาจะไม่เร็วกว่าวิธีอื่น
Mark Henderson

1
สิ่งนี้ดูมีแนวโน้ม แต่ฉันควรชี้แจงว่าบัญชีอยู่ในระบบ ฉันลองทำสิ่งต่อไปนี้: ([ADSI]'WinNT://localhost/USERNAME').ChangePassword("OLDPASS", "NEWPASS") แต่ที่ส่งคืน 'รหัสผ่านไม่เป็นไปตามข้อกำหนดนโยบายรหัสผ่าน ... ' รหัสผ่านใหม่ไม่เป็นไปตามข้อกำหนดเหล่านั้น
elijahbuck

1
จริงๆแล้วหลังจากเพิ่มผู้ใช้ไปที่ 'ผู้ใช้เดสก์ท็อประยะไกล' และพยายามเปลี่ยนรหัสผ่านด้วยวิธีนี้ฉันได้รับข้อผิดพลาดเดียวกัน ฉันเชื่อว่าวิธีที่ถูกต้องในการเปลี่ยนบัญชีท้องถิ่นคือ: ([ADSI]'WinNT://localhost/USERNAME').ChangePassword("OLDPASS", "NEWPASS")
elijahbuck

9

อันที่จริงแล้วมันค่อนข้างง่ายใน PowerShell:

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

3

ฉันลองทั้งสองคำตอบข้างต้นเพื่อไม่เป็นประโยชน์สำหรับการเปลี่ยนรหัสผ่านของผู้ดูแลระบบท้องถิ่นที่ไม่ได้เข้าร่วมโดเมน การขุดผ่านความคิดเห็นทำให้ได้สิ่งที่ฉันต้องการ

สำหรับส่วนที่สองของคำตอบที่ได้รับการยอมรับในปัจจุบันคุณต้องการปรับปรุงลายเซ็นที่จะใช้longแทนboolค่าตอบแทนและสิ่งเหล่านี้สามารถ troubleshooted มากกว่าที่เอกสารรหัสข้อผิดพลาดของระบบ ดังนั้นคุณจะจบลงด้วย:

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)

อย่างไรก็ตามนั่นไม่ได้ผลสำหรับฉัน รหัสข้อผิดพลาดสลับกันระหว่าง 86 และ 2221 ขึ้นอยู่กับวิธีตั้งค่าพารามิเตอร์ กำลังจะยอมแพ้และขุดมากขึ้นในความคิดเห็นและในที่สุดก็พบความสำเร็จในการทำ:

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

ไร้สาระอย่างแน่นอนว่าการเปลี่ยนรหัสผ่านของผู้ดูแลระบบในท้องถิ่นนั้นซับซ้อนใน Powershell หากคุณเก็บ securestrings ไว้ในระบบของคุณดังนั้นการอัพเดตรหัสผ่านจะต้องกระทำด้วยการจัดหารหัสผ่านเก่าหรือเสี่ยงต่อการสูญเสียความสามารถในการถอดรหัสสตริงที่ปลอดภัยเหล่านั้นอย่างถูกต้อง!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.