Alguna vez les paso que un usuario de Active Directory se les bloqueo varias veces una misma semana? Y un mismo día?
Bueno, a no preocuparse, con este pequeño script vamos a poder ver en donde se produce ese bloqueo o intento fallido de login para poder resolverlo fácilmente.
Antes que nada, necesitamos tener instaladas las herramientas de administración remota (también llamado RSAT).
Podemos bajarlas desde estos links:
Windows 7 x86
Windows 7 x64
Una vez instalados, solo queda abrir una ventana de Powershell y ejecutar el siguiente script.
function show-progressbar([int]$actual,[int]$completo,[string]$status,[string]$Activity) | |
{ | |
$porcentaje=($actual/$completo)*100 | |
if (!$status){ | |
$status="Buscando datos $actual de $completo" | |
} | |
if (!$Activity){ | |
$Activity="Obteniendo Resultados" | |
} | |
Write-Progress -Activity $Activity -status $status -percentComplete $porcentaje | |
} | |
############################################################### | |
# Ya explique esta funcion en este post # | |
# https://powershelleando.com.ar/2014/05/30/show-progressbar/ # | |
############################################################### | |
import-module activedirectory | |
$logcompleto=@() | |
$logdcs=@() | |
$cuentadc=1 | |
# crea una carpeta "Eventos". Si ya existe no hace nada. | |
New-Item -Name eventos -Type directory -Force | |
# Levanta todos los DCs | |
$dcs=Get-ADDomainController -Filter * | |
$dctotal=$dcs.count | |
foreach ($dc in $dcs){ | |
$nombredc=$dc.name | |
# Variable de ayuda para filtrar cuando no hay eventos | |
$sineventos=$false | |
$cuentaeventos=0 | |
# Variable de ayuda para filtrar eventos de no repeticion | |
$mostrar=$true | |
$tipo=" " | |
# Revisando Domain Controller $nombredc - Chequeando disponibilidad. | |
$Status="Revisando Domain Controller $nombredc ($cuentadc de $dctotal)- Chequeando disponibilidad." | |
show-progressbar $cuentadc $dctotal $status | |
$online = Test-Connection $nombredc -Quiet -count 1 | |
if ($online){ | |
# Revisando Domain Controller $nombredc - Recuperando eventos. | |
$Status="Revisando Domain Controller $nombredc ($cuentadc de $dctotal) - Recuperando eventos." | |
show-progressbar $cuentadc $dctotal $status | |
# Get-WinEvent busca en el log de eventos, usamos -FilterXPath | |
#para consultar por eventos especificos, en este caso, indicamos | |
#los dos EventIDs que nos pueden resultar interesantes. | |
# EventID=4740 es el evento de bloqueo de usuario | |
# EventID=4625 es el evento de intento fallido de login | |
$logs=(Invoke-Command -computername $nombredc -ScriptBlock {Get-WinEvent -FilterXml "<QueryList><Query Path='Security'><Select Path='Security'>*[System[(EventID=4740 or EventID=4625)]]</Select></Query></QueryList>" -ErrorAction silentlyContinue} ) | |
if ($logs -eq $null){ | |
# Marca que no hay eventos para acomodar | |
$sineventos=$true | |
$eventostotal=0 | |
} | |
if (!$sineventos){ | |
$eventostotal=$logs.count | |
# Revisa evento por evento | |
foreach ($evento in $logs){ | |
$cuentaeventos+=1 | |
# Revisando Domain Controller $nombredc - cantidad de eventos | |
$Status="Revisando Domain Controller $nombredc ($cuentadc de $dctotal) - Evento numero $cuentaeventos de $eventostotal" | |
show-progressbar $cuentadc $dctotal $status | |
# mensaje tiene la variable message del evento | |
$mensaje=$evento.message | |
$hora=$evento.TimeCreated.ToShortTimeString() | |
$fecha=$evento.TimeCreated.ToShortDateString() | |
$id=$evento.ID | |
$datos=$mensaje.Split("`n") | |
Switch ($id) | |
{ | |
4740{ | |
## CASE 4740 - Bloqueo de un usuario | |
# datos[10] tiene la linea del usuario | |
$usuario=(($datos[10].split("`t"))[3]) | |
# datos[13] tiene la linea del equipo que genero el evento | |
$Maquina=(($datos[13].split("`t"))[2]) | |
$tipo="Bloqueo" | |
## FIN CASE 4740 | |
} | |
4625{ | |
## CASE 4625 - Intento de login fallido | |
## (chequear por si es un error) | |
if ($evento.Providername -eq "Microsoft-Windows-Security-Auditing"){ | |
# datos[12] tiene la linea del usuario | |
$usuario=(($datos[12].split("`t"))[3]) | |
# datos[25] tiene la linea del equipo que | |
#genero el evento | |
$Maquina=(($datos[25].split("`t"))[2]) | |
$tipo="Intento de Login" | |
} | |
else{ | |
$mostrar=$false | |
} | |
## FIN CASE 4625 | |
} | |
default{ | |
## Hubo un error. | |
$usuario="ERROR" | |
$maquina="ERROR" | |
$tipo="ERROR" | |
} | |
} | |
if ($mostrar){ | |
$logcompleto+= $usuario | select-object @{Expression={$usuario};Label="Usuario"},@{Expression={$maquina};Label="Equipo"},@{Expression={$tipo};Label="Evento"},@{Expression={$fecha};Label="Fecha"},@{Expression={$Hora};Label="Hora"},@{Expression={$nombredc};Label="DC"} | |
} | |
} | |
} | |
} | |
else{ | |
# Si el domain controller no esta disponible | |
write-host "El domain controller $nombredc esta OFFLINE" -backgroundcolor "red" -ForegroundColor black | |
} | |
$logDCS+=$cuentadc|select-object @{Expression={$nombredc};Label="DC"}, @{Expression={$online};Label="Online"}, @{Expression={$cuentaeventos};Label="Eventos"} | |
$cuentadc+=1 | |
} | |
# Exporta el log de los usuarios bloqueados a CSV | |
$logcompleto| export-csv ./eventos/Log_Bloqueados.csv | |
# Exporta el log de estado de los DCs a CSV | |
$logdcs | export-csv ./eventos/log_dcs.csv | |
##Fin | |
Esto fue todo por hoy, si tienen alguna duda, comentario o sugerencia pueden escribirme mas abajo.
Hasta la próxima!