Compruebe si la entrada de contraseña de usuario es válida en el script de Powershell

30

Estoy trabajando con un script de Powershell que agrega tareas programadas a los sistemas en nuestro dominio. Cuando ejecuto este script, me pedirá mi contraseña. A veces apunto la contraseña y comienza el proceso, que bloquea mi cuenta. ¿Hay alguna forma de verificar mis credenciales para asegurarme de que lo que escribí se validará con el dominio?

Me gustaría encontrar una manera de consultar el controlador de dominio. He realizado algunas búsquedas en Google y debería poder hacer una consulta WMI y atrapar un error. Me gustaría evitar ese estilo de validación si es posible.

¿Algunas ideas? Gracias por adelantado.

Doltknuckle
fuente

Respuestas:

26

Tengo esto en mi biblioteca:

$cred = Get-Credential #Read credentials
 $username = $cred.username
 $password = $cred.GetNetworkCredential().password

 # Get current domain using logged-on user's credentials
 $CurrentDomain = "LDAP://" + ([ADSI]"").distinguishedName
 $domain = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain,$UserName,$Password)

if ($domain.name -eq $null)
{
 write-host "Authentication failed - please verify your username and password."
 exit #terminate the script.
}
else
{
 write-host "Successfully authenticated with domain $domain.name"
}
Jim B
fuente
1
Si no me equivoco, esto terminaría enviando la contraseña en texto plano a través de la red, ¿verdad? Si es así, ¿estoy en lo cierto al suponer que AccountManagement.PrincipalContext.ValidateCredentials()no (si proporciona una cadena de seguridad para la contraseña)?
Code Jockey
¿Por qué no estás usando el ActiveDirectorymódulo para hacer tu consulta LDAP?
Kolob Canyon
Hace 6 años no había un módulo de directorio activo
Jim B
Este script también ayuda en situaciones en las que no puede instalar los módulos AD PowerShell por una razón u otra.
Dodzi Dzakuma
16

Esto es lo que he usado en el pasado; se supone que funciona para cuentas de máquinas locales y 'directorio de aplicaciones', pero hasta ahora solo lo he usado con éxito con credenciales de AD:

    function Test-Credential {
    <#
    .SYNOPSIS
        Takes a PSCredential object and validates it against the domain (or local machine, or ADAM instance).

    .PARAMETER cred
        A PScredential object with the username/password you wish to test. Typically this is generated using the Get-Credential cmdlet. Accepts pipeline input.

    .PARAMETER context
        An optional parameter specifying what type of credential this is. Possible values are 'Domain','Machine',and 'ApplicationDirectory.' The default is 'Domain.'

    .OUTPUTS
        A boolean, indicating whether the credentials were successfully validated.

    #>
    param(
        [parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [System.Management.Automation.PSCredential]$credential,
        [parameter()][validateset('Domain','Machine','ApplicationDirectory')]
        [string]$context = 'Domain'
    )
    begin {
        Add-Type -assemblyname system.DirectoryServices.accountmanagement
        $DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::$context) 
    }
    process {
        $DS.ValidateCredentials($credential.UserName, $credential.GetNetworkCredential().password)
    }
}
jbsmith
fuente
Me encantaría saber si alguien se da cuenta de esto: creo que cuando uso ValidateCredentials () de esta manera con una contraseña incorrecta, parece desencadenar dos (2) intentos de contraseña incorrecta: no puedo controlar el umbral del número de intentos en nuestro dominio, y es bajo, por lo que preferiría no tener dos intentos fallidos cuando hago una sola llamada ... ¿Alguien puede ver esto también?
Code Jockey
¿Está utilizando el formato dominio \ usuario o UPN (usuario @ dominio)? No estoy en condiciones de replicar esto, pero la siguiente URL describe un problema similar: social.msdn.microsoft.com/Forums/vstudio/en-US/…
jbsmith
Debería poder pasar $contextcomo argumento al constructor. PowerShell convertirá automáticamente las cadenas en una enumeración. Mejor aún, solo haz [System.DirectoryServices.AccountManagement.ContextType]el tipo de $context. Además, ¿por qué estás usando beginy processaquí? La canalización parece una forma extraña de usar esta función.
jpmc26
@ jpmc26: escribir el $contextparámetro [System.DirectoryServices.AccountManagement.ContextType]no es una opción, porque el ensamblado que contiene no se carga hasta que se ejecuta el cuerpo de la función ; usar la canalización es útil si desea validar múltiples credenciales.
Mklement
@mklement No hay razón para que la Add-Typellamada no se pueda mover fuera de la función, antes de que se ejecute su definición. Dudo que una Add-Typellamada se ejecute incondicionalmente repetidamente dentro de la función, incluso si ya está cargada, de todos modos. Validar múltiples credenciales simultáneamente parece una situación extraña en primer lugar. En el raro caso de que eso sea lo que desea, puede completar fácilmente la llamada ForEach-Object, por lo que no veo una razón para complicar la función con ella.
jpmc26
1

Esta publicación me pareció útil, sin embargo, no resolvió mi problema, ya que estaba tratando de ejecutarla desde un script con la cuenta de administrador local conectada. No parece funcionar como administrador local (solo cuando está conectado como usuario de dominio).

Sin embargo, finalmente logré obtener una solución que funcionara y, dado que era un problema, pensé en compartirla aquí para que cualquier otra persona con este problema tenga la respuesta aquí. Ambas respuestas en una página, según sus necesidades.

Tenga en cuenta que más arriba en el scipt (no incluido aquí, ya que esta es solo la sección de obtención de credenciales) powergui está instalado y es un requisito para este código a continuación (así como la línea "Add-PSSnapin Quest.ActiveRoles.ADManagement"). No estoy seguro de qué powergui hace es diferente, pero nadie más podría decirme y funciona.

Sustituya su propio nombre de dominio en las secciones "nombre_dominio".

#Get credentials
$credential_ok = 0
while ($credential_ok -ne 1)
{
    $credential = get-credential
    $result = connect-qadservice -service *domain_name* -credential $credential
    [string]$result_string = $result.domain
    if ($result_string -eq "*domain_name*")
    {
        $credential_ok = 1
        #authenticated
    }
    else
    {
        #failed
    }     
}
$username = $credential.username 
$password = $credential.GetNetworkCredential().password 

$date = get-date
Add-Content "c:\lbin\Install_log.txt" "Successfully authenticated XP script as $username $date"
Miguel
fuente
1

(todavía) Otra versión:

param([string]$preloadServiceAccountUserName = "")

function HarvestCredentials()
{

        [System.Management.Automation.PSCredential]$credentialsOfCurrentUser = Get-Credential -Message "Please enter your username & password" -UserName $preloadServiceAccountUserName

        if ( $credentialsOfCurrentUser )
        {
            $credentialsOfCurrentUser = $credentialsOfCurrentUser
        }
        else
        {
            throw [System.ArgumentOutOfRangeException] "Gui credentials not entered correctly"          
        }

    Try
    {


        # see https://msdn.microsoft.com/en-us/library/system.directoryservices.directoryentry.path(v=vs.110).aspx
        # validate the credentials are legitimate
        $validateCredentialsTest = (new-object System.DirectoryServices.DirectoryEntry ("WinNT://"+$credentialsOfCurrentUser.GetNetworkCredential().Domain), $credentialsOfCurrentUser.GetNetworkCredential().UserName, $credentialsOfCurrentUser.GetNetworkCredential().Password).psbase.name
        if ( $null -eq  $validateCredentialsTest)
        {
            throw [System.ArgumentOutOfRangeException] "Credentials are not valid.  ('" + $credentialsOfCurrentUser.GetNetworkCredential().Domain + '\' + $credentialsOfCurrentUser.GetNetworkCredential().UserName + "')"
        }
        else
        {
            $t = $host.ui.RawUI.ForegroundColor
            $host.ui.RawUI.ForegroundColor = "Magenta"
            Write-Output "GOOD CREDENTIALS"
            $host.ui.RawUI.ForegroundColor = $t
        }
    }
    Catch
    {

        $ErrorMessage = $_.Exception.Message
        $FailedItem = $_.Exception.ItemName
        $StackTrace = $_.Exception.StackTrace

        $t = $host.ui.RawUI.ForegroundColor
        $host.ui.RawUI.ForegroundColor = "Red"

        Write-Output "Exception - $ErrorMessage"
        Write-Output "Exception - $FailedItem"
        Write-Output "Exception - $StackTrace"

        $host.ui.RawUI.ForegroundColor = $t

        throw [System.ArgumentOutOfRangeException] "Attempt to create System.DirectoryServices.DirectoryEntry failed.  Most likely reason is that credentials are not valid."
    }

}


Try
{

    HarvestCredentials

}
Catch
{
    $ErrorMessage = $_.Exception.Message
    $FailedItem = $_.Exception.ItemName
    $StackTrace = $_.Exception.StackTrace

    $t = $host.ui.RawUI.ForegroundColor
    $host.ui.RawUI.ForegroundColor = "Red"

    Write-Output "Exception - " + $ErrorMessage
    Write-Output "Exception - " + $FailedItem
    Write-Output "Exception - " + $StackTrace

    $host.ui.RawUI.ForegroundColor = $t

    Break
}
Finally
{
    $Time=Get-Date
    Write-Output "Done - " + $Time
}

y

.\TestCredentials.ps1 -preloadServiceAccountUserName "mydomain\myusername"
granadaCoder
fuente