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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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!