当用户使用 ADSI 脚本时防止权限升级

Prevent privilege escalation when a user utilizes an ADSI script

我创建了一个脚本,允许用户更改另一个用户的密码(如果获得许可)。该脚本使用 ADSI,只能通过启动电源 shell GUI 的快捷方式访问。我用来更改密码的代码如下。

$pwd = "Password1"
    $user = (([adsisearcher]"(&(objectCategory=User)(samaccountname=$username))").findall()).properties.distinguishedname
    $oUser = [adsi]“LDAP://$user”
    $ouser.psbase.invoke(“SetPassword”,$pwd)
    $ouser.psbase.CommitChanges()

脚本本身已被锁定以供编辑,用户访问它的唯一方法是通过我给他们的快捷方式。一位上级同事喜欢该脚本,但担心权限提升 我的问题是,如果我将用户的密码更改能力限制为仅某个 OU,他们是否能够通过该脚本提升权限?我们的 OU 的设置方式是每个人都包含在他们的 OU 中,除非他们是主管或董事。此脚本仅供主管使用。

编辑:我意识到放置完整代码而不只是密码更改代码对我来说是有益的。在这里。

#---------------------------------------------------------[Initialisations]--------------------------------------------------------
# Init PowerShell Gui
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# Hide PowerShell Console
Add-Type -Name Window -Namespace Console -MemberDefinition '
[DllImport("Kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'
$consolePtr = [Console.Window]::GetConsoleWindow()
[Console.Window]::ShowWindow($consolePtr, 0)
#---------------------------------------------------------[Form]--------------------------------------------------------
$stayopen =  3
while($stayopen -ne  2){
[System.Windows.Forms.Application]::EnableVisualStyles()
$LocalResetPassForm                    = New-Object system.Windows.Forms.Form
$LocalResetPassForm.ClientSize         = '480,300'
$LocalResetPassForm.text               = "Reset Staff Password"
$LocalResetPassForm.BackColor          = "#ffffff"
$LocalResetPassForm.TopMost            = $false


$Errorhandleform                       = New-Object system.Windows.Forms.Form
$Errorhandleform.ClientSize            = '480,300'
$Errorhandleform.text                  = "Reset Staff Password"
$Errorhandleform.BackColor             = "#ffffff"
$Errorhandleform.TopMost               = $false


$Titel                           = New-Object system.Windows.Forms.Label
$Titel.text                      = "Reset Staff Password"
$Titel.AutoSize                  = $true
$Titel.width                     = 25
$Titel.height                    = 10
$Titel.location                  = New-Object System.Drawing.Point(20,20)
$Titel.Font                      = 'Microsoft Sans Serif,13'


$Description                     = New-Object system.Windows.Forms.Label
$Description.text                = "Clicking Change Password will change the Password of the account to Password1 and unlock the user's account"
$Description.AutoSize            = $false
$Description.width               = 450
$Description.height              = 50
$Description.location            = New-Object System.Drawing.Point(20,50)
$Description.Font                = 'Microsoft Sans Serif,10'

$Errorhandle                     = New-Object system.Windows.Forms.Label
$Errorhandle.text                = "We are unable to find the Username you provided please try again."
$Errorhandle.AutoSize            = $false
$Errorhandle.width               = 450
$Errorhandle.height              = 50
$Errorhandle.location            = New-Object System.Drawing.Point(20,50)
$Errorhandle.Font                = 'Microsoft Sans Serif,10'


$TryAgainBtn                   = New-Object system.Windows.Forms.Button
$TryAgainBtn.BackColor         = "#ffffff"
$TryAgainBtn.text              = "Try Again"
$TryAgainBtn.width             = 140
$TryAgainBtn.height            = 30
$TryAgainBtn.location          = New-Object System.Drawing.Point(330,250)
$TryAgainBtn.Font              = 'Microsoft Sans Serif,10'
$TryAgainBtn.ForeColor         = "#000"
$TryAgainBtn.Visible           = $true
$TryAgainBtn.DialogResult      = [System.Windows.Forms.DialogResult]::OK
$TryAgainBtn.AcceptButton = $ResetPassBtn


$ResetPassBtn                   = New-Object system.Windows.Forms.Button
$ResetPassBtn.BackColor         = "#ffffff"
$ResetPassBtn.text              = "Change Password"
$ResetPassBtn.width             = 140
$ResetPassBtn.height            = 30
$ResetPassBtn.location          = New-Object System.Drawing.Point(330,250)
$ResetPassBtn.Font              = 'Microsoft Sans Serif,10'
$ResetPassBtn.ForeColor         = "#000"
$ResetPassBtn.Visible           = $true
$ResetPassBtn.DialogResult      = [System.Windows.Forms.DialogResult]::OK
$LocalResetPassForm.AcceptButton = $ResetPassBtn
$LocalResetPassForm.Controls.Add($ResetPassBtn)


$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(20,100)
$label.Size = New-Object System.Drawing.Size(320,20)
$label.Text = 'Enter The Staff Members username in the space Below:'
$LocalResetPassForm.Controls.Add($label)

$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(20,120)
$textBox.Size = New-Object System.Drawing.Size(300,20)
$LocalResetPassForm.Controls.Add($textBox)

$cancelBtn                       = New-Object system.Windows.Forms.Button
$cancelBtn.BackColor             = "#ffffff"
$cancelBtn.text                  = "Cancel"
$cancelBtn.width                 = 90
$cancelBtn.height                = 30
$cancelBtn.location              = New-Object System.Drawing.Point(230,250)
$cancelBtn.Font                  = 'Microsoft Sans Serif,10'
$cancelBtn.ForeColor             = "#000"
$cancelBtn.DialogResult          = [System.Windows.Forms.DialogResult]::Cancel

$LocalResetPassForm.CancelButton = $cancelBtn
$LocalResetPassForm.Controls.Add($cancelBtn)
$LocalResetPassForm.controls.AddRange(@($Titel,$Description,$cancelBtn))
$LocalResetPassForm.Topmost      = $true
$LocalResetPassForm.Add_Shown({$textBox.Select()})
$result                          = $LocalResetPassForm.ShowDialog()
$stayopen =  2
if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
    $username                    = $textBox.Text




    #find if user exists
    $finduser                    = (([adsisearcher]"(&(objectCategory=User)(samaccountname=$username))").findall()).properties.distinguishedname
    #if user does not exist
    if (!$finduser)
    { 
    #open error window and set try again button
    $Errorhandleform.controls.AddRange(@($Errorhandle,$TryAgainBtn))
    $tryagain                    = $Errorhandleform.ShowDialog()
    if ($tryagain -eq [System.Windows.Forms.DialogResult]::OK)
      {
       $stayopen =  3
      }
    }

    #Change the Password
    $pwd = "Password1"
    $user = (([adsisearcher]"(&(objectCategory=User)(samaccountname=$username))").findall()).properties.distinguishedname
    $ouser = [adsi]“LDAP://$user”
    $ouser.psbase.invoke(“SetPassword”,$pwd)
    $ouser.lockoutTime = 0
    $ouser.pwdLastSet = 0
    $ouser.psbase.CommitChanges()

    
    
}
}

此外,用户只能访问将此行作为目标的快捷方式 C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -File "T:\Scripts\passwordgui.ps1"

尝试使用上述 PowerShell 并进行了修改,但它对我不起作用

您可以遵循一种解决方法,通过授予特定 OU 的读取和重置用户密码的委派权限,允许特定用户更改其他用户的密码。

步骤 1:将 OU 的委派权限授予任何特定用户以更改同一 OU 用户的密码。

步骤 2允许 Local on locally 该特定用户登录到 Active Directory 用户和计算机并重置密码特定 OU 的另一个用户(您已授予委派权限)。

参考:Allow log on locally - security policy setting (Windows 10) - Windows security | Microsoft Docs

步骤 3:使用特定用户登录 VM 以重置另一个用户的密码

可以使用一个特定用户更改 OU 用户的密码