🔍 Monitorización de logins en Windows con PowerShell: detecta intrusiones antes de que sea tarde
hace 5 meses

Monitoriza logins en Windows con PowerShell
Monitorización de logins en Windows es la capa defensiva que convierte el registro de seguridad —activo pero ignorado en la mayoría de los equipos— en una alarma real. El tiempo medio que un atacante permanece dentro de un sistema comprometido sin ser detectado se mide en meses, no en horas, y la causa casi siempre es la misma: nadie revisa ese registro.
Este artículo documenta un único script de PowerShell que automatiza el análisis de los eventos 4624, 4625, 4672 y 4740 mediante tres tareas programadas, detectando fuerza bruta, password spraying, Pass-the-Hash y logins fuera de horario sin instalar herramientas externas. Según los informes de referencia sobre tiempo de permanencia de atacantes, la mediana de detección sin monitorización activa asciende a semanas o meses. Incluye además el mapeo completo a MITRE ATT&CK y la integración con SIEM y Sysmon. Para profundizar en el resto de medidas de bastionado del sistema operativo, conviene revisar también la recopilación de guías de seguridad en Windows para blindar el equipo frente a accesos no autorizados.
⚡ Respuesta rápida
Sí, con un único script de PowerShell puedes monitorizar los logins de Windows en minutos: activa la auditoría de Logon, Special Logon y Account Lockout por GUID, y analiza cuatro eventos clave — 4625 (login fallido), 4624 (login exitoso), 4672 (privilegios especiales) y 4740 (cuenta bloqueada). Tres tareas programadas (inicio, logon y cada hora) automatizan el análisis y detectan fuerza bruta, password spraying y campañas lentas repartidas en semanas, dejando constancia en un CSV histórico. El script es de solo lectura: no modifica cuentas, firewall ni servicios.
💡 Definición rápida
Monitorización de logins en Windows: Práctica de activar la política de auditoría de Windows y analizar de forma continua los eventos de autenticación registrados en el log Security (4624, 4625, 4672 y 4740) para detectar fuerza bruta, password spraying, escalación de privilegios y accesos anómalos, reduciendo el tiempo de detección de un ataque de semanas o meses a horas.
💡 Resumen rápido
🔍 Monitorización de logins en Windows: detecta intrusos con PowerShell
Sin esta vigilancia, un atacante con credenciales válidas puede pasar meses dentro del sistema sin dejar rastro visible.
- ✅ 4 eventos clave: 4624, 4625, 4672 y 4740
- ✅ 5 ataques detectables: fuerza bruta, password spraying, credential stuffing, escalación y movimiento lateral
- ✅ Script con 3 tareas programadas: inicio, logon y cada hora
- ✅ CSV histórico para detectar campañas lentas repartidas en semanas
- ✅ Solo lectura: no modifica cuentas, firewall ni servicios
.ps1 en C:\Scripts y ejecútalo como administrador. Activa la auditoría de Logon, Special Logon y Account Lockout por GUID (evita el error 0x00000057 de auditpol en Windows en español) y analiza cuatro eventos clave: 4625 (login fallido), 4624 (login exitoso), 4672 (privilegios especiales) y 4740 (cuenta bloqueada). Tres tareas programadas automatizan el análisis dejando constancia en un CSV histórico que detecta campañas lentas repartidas en semanas. Tras la primera ejecución hay que reiniciar el equipo una vez para que las tareas queden visibles y activas.📅 Publicado: 26 de febrero de 2026 · 🕒 Tiempo de lectura: 19 minutos

📌 ¿Qué es la monitorización de logins en Windows?
La monitorización de logins en Windows consiste en activar la política de auditoría y analizar de forma continua los eventos del log Security. Con un script PowerShell detecta:
- Fuerza bruta y password spraying contra cuentas locales o de dominio (eventos 4625)
- Accesos exitosos en horarios anómalos (evento 4624 entre 00:00 y 06:00)
- Escalaciones de privilegios mediante el evento 4672
- Cuentas bloqueadas (4740) tras superar el umbral de intentos
- Campañas lentas de credential stuffing gracias al CSV histórico ilimitado
El dwell time medio sin monitorización activa asciende a semanas o meses según M-Trends. Con este script se reduce a horas.
La monitorización de logins en Windows consiste en activar la política de auditoría y analizar de forma continua los eventos que el sistema registra cada vez que un usuario intenta autenticarse. Windows escribe esta información en el log Security, accesible desde PowerShell con Get-WinEvent.
- ✔ Detecta fuerza bruta y password spraying contra cuentas locales o de dominio.
- ✔ Identifica accesos exitosos en horarios anómalos.
- ✔ Registra escalaciones de privilegios mediante el evento 4672.
- ✔ Captura cuentas bloqueadas (4740) tras superar el umbral de intentos.
- ✔ Convierte el análisis puntual en serie histórica con CSV.
- ✔ Sienta la base para integración con SIEM (Splunk, Elastic, Wazuh, Sentinel).
El credential stuffing que detecta este script explota credenciales previamente filtradas en brechas de datos. Activa las alertas de Dark Web Monitoring para saber si tus credenciales ya circulan en mercados clandestinos antes de que un atacante las use contra tu sistema.
🔢 Los cuatro eventos clave
Los cuatro Event IDs críticos del log Security para detectar intrusiones en Windows:
- 4624 — Login exitoso (MITRE T1078): detecta accesos en horario inhabitual o desde IP desconocida
- 4625 — Login fallido (MITRE T1110): decenas de fallos seguidos indican fuerza bruta; fallos distribuidos en muchas cuentas indican password spraying
- 4672 — Privilegios especiales asignados (T1078/T1068): cuenta normal con derechos sensibles = escalación de privilegios
- 4740 — Cuenta bloqueada (T1110): la política de bloqueo ha actuado — investiga la causa inmediatamente
Cada Event ID de esta tabla está mapeado a su técnica correspondiente en el framework MITRE ATT&CK, la referencia estándar del sector para clasificar tácticas y técnicas de ataque. Para la configuración detallada de las subcategorías de auditoría por GPO en entornos de dominio, consulta la documentación oficial de Microsoft sobre políticas de auditoría.
| Event ID | Significado | Qué indica un volumen anómalo | MITRE |
|---|---|---|---|
| 4624 | Login exitoso | Login en horario inhabitual o IP desconocida | T1078 |
| 4625 | Login fallido | Decenas de fallos seguidos = fuerza bruta | T1110 |
| 4672 | Privilegios especiales asignados | Cuenta normal con derechos sensibles = escalación | T1078/T1068 |
| 4740 | Cuenta bloqueada | Política de bloqueo activada | T1110 |
🔐 Logon Types: qué significa cada tipo en el evento 4624
| Type | Nombre | Cuándo aparece | Riesgo |
|---|---|---|---|
| 2 | Interactive | Login en consola física | 🟡 Acceso físico no autorizado |
| 3 | Network | SMB, recurso compartido | 🔴 Movimiento lateral, Pass-the-Hash |
| 4 | Batch | Tareas programadas con credenciales | 🟠 Persistencia (T1053) |
| 5 | Service | Inicio de servicios | 🟠 Servicios maliciosos (T1543.003) |
| 7 | Unlock | Desbloqueo de sesión | 🟡 Acceso físico tras ausencia |
| 8 | NetworkCleartext | Credenciales en claro (IIS Basic Auth) | 🔴 Credenciales expuestas |
| 10 | RemoteInteractive | RDP, Terminal Services | 🔴 RDP brute force |
| 11 | CachedInteractive | Login con credenciales cacheadas | 🟡 Pass-the-Hash en cache |
🚨 5 ataques que detecta la monitorización de logins en Windows
| Ataque | Patrón en el log | Ventana | MITRE |
|---|---|---|---|
| Fuerza bruta | Decenas de 4625 desde la misma IP en minutos | Inmediata | T1110.001 |
| Password spraying | Pocos 4625 contra muchos usuarios distintos | Hora a día | T1110.003 |
| Credential stuffing | 4624 exitoso desde IP nueva sin 4625 previos | Inmediata | T1078.004 |
| Escalación de privilegios | 4672 en cuenta sin derechos especiales habituales | Inmediata | T1068 |
| Movimiento lateral | 4624 con LogonType 3 entre equipos sin justificación | Día a semana | T1021 |
Para cerrar el vector de fuerza bruta y password spraying que detecta este script, aplica la guía técnica de hardening de cuentas Windows: política de contraseñas, bloqueo y auditoría con PowerShell — ambos scripts son complementarios: el hardening bloquea el ataque y este script lo detecta y lo registra.

⚙️ Script completo de monitorización de logins en Windows con 3 tareas programadas
C:\Logs\monitor-logins.log y CSV en C:\Logs\monitor-logins-historico.csv.📅 Las 3 tareas programadas de la monitorización de logins en Windows
| Tarea | Disparador | Frecuencia | Propósito |
|---|---|---|---|
Monitor-Logins-Inicio | Al iniciar Windows | Cada arranque | Reaplica la auditoría y analiza las últimas 24h tras reinicio o actualización |
Monitor-Logins-Logon | Al iniciar sesión | Cada login | Analiza eventos inmediatamente tras el logon |
Monitor-Logins-Horaria | Cada hora | 24 veces/día | Vigilancia continua; detecta campañas lentas |
La misma metodología de script + tareas programadas está documentada en el script completo para endurecer Windows 11 con 7 tareas programadas — ambos scripts son complementarios y pueden ejecutarse juntos para un hardening y monitorización integral.
📥 Cómo guardar y ejecutar el script paso a paso
C:\Scripts, una carpeta fija que no se mueve ni se borra por accidente.1. Cómo guardar el script de monitorización de logins en Windows como .ps1 en C:\Scripts
- Si no la tienes ya, crea la carpeta
C:\Scripts: abre el Explorador de archivos, ve aC:\, clic derecho → Nuevo → Carpeta, y ponle de nombreScripts. - Abre el Bloc de notas (tecla Windows → escribe "Bloc de notas" → Enter).
- Pega dentro el código del script completo (lo tienes al final de esta sección).
- Ve a Archivo → Guardar como. Rellena estos tres campos:
- Dónde guardarlo: navega hasta
C:\Scripts(no el Escritorio). - Nombre de archivo: escribe
monitor-logins.ps1(con el.ps1al final, escrito por ti). - Tipo: cambia el desplegable de "Documentos de texto (*.txt)" a "Todos los archivos (*.*)". Si no lo cambias, el archivo se guarda como
monitor-logins.ps1.txtaunque hayas escrito ".ps1".
- Dónde guardarlo: navega hasta
- Pulsa Guardar.
- Comprueba que salió bien: en
C:\Scripts, el icono del archivo debe verse como una pantalla de consola azul, no como una hoja de papel.
2. Cómo se ejecuta
Nunca hagas doble clic sobre el archivo ni pegues el código directamente en la consola de PowerShell.
- Pulsa la tecla Windows, escribe
PowerShell. - Haz clic derecho sobre "Windows PowerShell" y elige "Ejecutar como administrador". Confirma si te lo pide.
- En la ventana azul que se abre, escribe estas tres líneas una a una, pulsando Enter después de cada una:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass cd C:\Scripts dir *.ps1
Condir *.ps1confirmas el nombre exacto del archivo tal como quedó guardado. - Ejecuta el script con este comando:
powershell -NoExit -ExecutionPolicy Bypass -File "monitor-logins.ps1"
- Apenas verás texto en pantalla al principio, mientras se activa la auditoría y se amplía el log Security: el script usa
Start-Transcript, que captura esa salida enC:\Logs\monitor-logins.log. Es normal, espera a que continúe. - Después sí verás en pantalla las 3 líneas de confirmación de las tareas programadas (
[OK] Tarea '...' creada). - Al terminar te pedirá pulsar Enter para cerrar.
3. Reiniciar el equipo (obligatorio)
Reinicia el equipo una vez tras la primera ejecución. El Programador de tareas de Windows tarda en sincronizar visualmente las tareas recién creadas: hasta que reinicias, es posible que Get-ScheduledTask y el Programador de tareas gráfico no muestren las 3 tareas nuevas, aunque ya existan y estén correctamente registradas. Es un comportamiento normal, no un fallo del script. La tarea Monitor-Logins-Inicio se ejecutará automáticamente en ese mismo reinicio y generará la primera fila del CSV histórico.
Tras reiniciar, verifica:
Get-ScheduledTask -TaskName "Monitor-Logins-*" | Select-Object TaskName, TaskPath, State
Deben aparecer las 3 tareas, todas con TaskPath = \SeguridadEnMiPC\Monitor-Logins\ y State = Ready.
Si algo falla
- El script no muestra nada en pantalla al principio: normal, esa parte se registra en el log. Revisa con
Get-Content C:\Logs\monitor-logins.log -Tail 30. - Dice que la ejecución de scripts está deshabilitada: ejecuta primero
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass. - "El término 'finally' no se reconoce..." o errores de try/catch: pegaste el código directo en la consola en vez de guardarlo como archivo. Guárdalo como
.ps1(paso 1) y ejecútalo con-File(paso 2). - "El argumento '...' para el parámetro -File no existe": el nombre no coincide con el archivo guardado. Ejecuta
dir *.ps1enC:\Scriptsy usa el nombre exacto que aparece ahí. - Errores 0x00000057 en auditpol: ya resuelto en este script — usa GUIDs de subcategoría (
{0CCE9215-...},{0CCE921B-...},{0CCE9217-...}) en vez de nombres como "Logon" o "Special Logon", que en Windows en español no siempre coinciden exactamente y provocan ese error. - Las 3 tareas no aparecen en
Get-ScheduledTaskni en el Programador de tareas gráfico, aunque el log confirme que se crearon: problema de caché del Programador de tareas tras crear/recrear carpetas de tareas en la misma sesión. Reinicia el equipo (paso 3) — el servicio Schedule no se puede reiniciar manualmente, Windows lo bloquea por ser un servicio crítico. - Los contadores del CSV muestran 0: la auditoría estaba desactivada antes de ejecutar el script y solo registra eventos a partir de ese momento. Espera a que se dispare la tarea horaria o de logon y vuelve a revisar.
- Si al hacer clic derecho no aparece "Ejecutar como administrador": asegúrate de buscar "Windows PowerShell" (la app), no dentro de una carpeta. Prueba también "Terminal" en Windows 11.
# ============================================
# Monitorizacion de logins Windows
# Eventos 4624, 4625, 4672 y 4740
# y mantenimiento con tres tareas programadas
# Requiere: PowerShell como Administrador
# Ruta fija: C:\Scripts\monitor-logins.ps1
# ============================================
try {
# 0. Verificar privilegios de administrador
if (-not ([Security.Principal.WindowsPrincipal] `
[Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(`
[Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Host "[X] Ejecuta este script como Administrador." -ForegroundColor Red
exit
}
# 1. Asegurar que el script vive en C:\Scripts (ruta que usaran las tareas programadas)
$carpetaScripts = "C:\Scripts"
if (-not (Test-Path $carpetaScripts)) {
New-Item -ItemType Directory -Path $carpetaScripts -Force | Out-Null
}
$rutaFinal = "$carpetaScripts\monitor-logins.ps1"
if ($PSCommandPath -and ($PSCommandPath -ne $rutaFinal)) {
Copy-Item -Path $PSCommandPath -Destination $rutaFinal -Force
Write-Host "[i] Copia del script guardada en $rutaFinal para uso de las tareas programadas." -ForegroundColor Cyan
}
$carpetaLogs = "C:\Logs"
if (-not (Test-Path $carpetaLogs)) {
New-Item -ItemType Directory -Path $carpetaLogs -Force | Out-Null
}
Start-Transcript -Path "$carpetaLogs\monitor-logins.log" -Append | Out-Null
# 2. Habilitar auditoria: Logon (4624/4625), Special Logon (4672) y Account Lockout (4740)
# GUID en vez de nombre de subcategoria: evita el error 0x00000057 en Windows en espanol
auditpol /set /subcategory:"{0CCE9215-69AE-11D9-BED3-505054503030}" /success:enable /failure:enable | Out-Null
auditpol /set /subcategory:"{0CCE921B-69AE-11D9-BED3-505054503030}" /success:enable /failure:enable | Out-Null
auditpol /set /subcategory:"{0CCE9217-69AE-11D9-BED3-505054503030}" /success:enable /failure:enable | Out-Null
Write-Host "[OK] Auditoria habilitada: Logon, Special Logon y Account Lockout (eventos 4624/4625/4672/4740)." -ForegroundColor Green
# 3. Ampliar el log Security a 200 MB para no perder historico por rotacion
wevtutil sl Security /ms:209715200
Write-Host "[OK] Log Security ampliado a 200 MB." -ForegroundColor Green
# 4. Registrar esta ejecucion en el CSV historico
# Export-Csv -Append crea el archivo con su fila de encabezado real si aun no existe,
# asi que no hace falta escribir a mano una fila-encabezado de relleno.
$csvHistorico = "$carpetaLogs\monitor-logins-historico.csv"
if (-not (Test-Path $csvHistorico)) {
Write-Host "[i] El CSV historico se creara en la primera ejecucion del script de analisis." -ForegroundColor Yellow
} else {
Write-Host "[i] El CSV historico ya existia." -ForegroundColor Yellow
}
# 5. Crear script auxiliar de analisis (usado por Inicio/Logon/Horaria)
$carpetaAuxiliar = "C:\ProgramData\SeguridadEnMiPC\MonitorLogins"
if (-not (Test-Path $carpetaAuxiliar)) { New-Item -ItemType Directory -Path $carpetaAuxiliar -Force | Out-Null }
$scriptAnalizar = "$carpetaAuxiliar\analizar-logins.ps1"
$contenidoAnalizar = @'
# Reaplicar auditoria por si se reseteo (actualizacion, GPO, etc.)
auditpol /set /subcategory:"{0CCE9215-69AE-11D9-BED3-505054503030}" /success:enable /failure:enable | Out-Null
auditpol /set /subcategory:"{0CCE921B-69AE-11D9-BED3-505054503030}" /success:enable /failure:enable | Out-Null
auditpol /set /subcategory:"{0CCE9217-69AE-11D9-BED3-505054503030}" /success:enable /failure:enable | Out-Null
$csvHistorico = "C:\Logs\monitor-logins-historico.csv"
$ventana = (Get-Date).AddHours(-24)
$e4624 = Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4624; StartTime=$ventana} -ErrorAction SilentlyContinue
$e4625 = Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625; StartTime=$ventana} -ErrorAction SilentlyContinue
$e4672 = Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4672; StartTime=$ventana} -ErrorAction SilentlyContinue
$e4740 = Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4740; StartTime=$ventana} -ErrorAction SilentlyContinue
$ipsFallidas = @()
$cuentasFallidas = @()
$fueraHorario = 0
# LogonType 2 = interactivo, 10 = RDP/interactivo remoto.
# Excluye tipos 3 (red), 4 (batch), 5 (servicio), etc. para que el contador
# refleje accesos humanos reales y no las tareas programadas de SYSTEM.
$tiposLogonHumano = @('2', '10')
foreach ($evento in $e4625) {
[xml]$xml = $evento.ToXml()
$datos = $xml.Event.EventData.Data
$ip = ($datos | Where-Object { $_.Name -eq 'IpAddress' }).'#text'
$cuenta = ($datos | Where-Object { $_.Name -eq 'TargetUserName' }).'#text'
if ($ip -and $ip -ne '-') { $ipsFallidas += $ip }
if ($cuenta -and $cuenta -notmatch '\$$') { $cuentasFallidas += $cuenta }
}
foreach ($evento in $e4624) {
[xml]$xml = $evento.ToXml()
$datos = $xml.Event.EventData.Data
$tipoLogon = ($datos | Where-Object { $_.Name -eq 'LogonType' }).'#text'
if ($tipoLogon -in $tiposLogonHumano) {
$hora = $evento.TimeCreated.Hour
if ($hora -ge 0 -and $hora -lt 6) { $fueraHorario++ }
}
}
$ipsUnicas = ($ipsFallidas | Select-Object -Unique).Count
$cuentasUnicas = ($cuentasFallidas | Select-Object -Unique).Count
# Fuerza bruta: 20+ fallos en 24h desde la misma IP
$alertaFuerzaBruta = $false
$ipsFallidas | Group-Object | Where-Object { $_.Count -ge 20 } | ForEach-Object { $alertaFuerzaBruta = $true }
# Password spraying: 5+ cuentas distintas con fallos en la misma ventana
$alertaSpraying = ($cuentasUnicas -ge 5)
$fila = [PSCustomObject]@{
Fecha = Get-Date
LoginsExitosos = ($e4624 | Measure-Object).Count
LoginsFallidos = ($e4625 | Measure-Object).Count
PrivilegiosEspeciales = ($e4672 | Measure-Object).Count
CuentasBloqueadas = ($e4740 | Measure-Object).Count
IPsUnicasFallidas = $ipsUnicas
CuentasUnicasFallidas = $cuentasUnicas
AlertaFuerzaBruta = $alertaFuerzaBruta
AlertaSpraying = $alertaSpraying
LoginsFueraHorario = $fueraHorario
}
$fila | Export-Csv -Path $csvHistorico -NoTypeInformation -Encoding UTF8 -Append
Add-Content -Path "C:\Logs\monitor-logins.log" -Value "$(Get-Date) - [OK] Analisis completado: $($fila.LoginsExitosos) exitos, $($fila.LoginsFallidos) fallos, $($fila.CuentasBloqueadas) bloqueos"
if ($alertaFuerzaBruta) {
Add-Content -Path "C:\Logs\monitor-logins.log" -Value "$(Get-Date) - [ALERTA] Posible fuerza bruta: 20+ fallos en 24h desde una misma IP"
}
if ($alertaSpraying) {
Add-Content -Path "C:\Logs\monitor-logins.log" -Value "$(Get-Date) - [ALERTA] Posible password spraying: $cuentasUnicas cuentas distintas con fallos en 24h"
}
'@
Set-Content -Path $scriptAnalizar -Encoding UTF8 -Value $contenidoAnalizar
Write-Host "[OK] Script de analisis creado en $scriptAnalizar" -ForegroundColor Green
# 6. Carpeta de tareas programadas
$carpetaTareas = "\SeguridadEnMiPC\Monitor-Logins\"
# 7. Tarea: verificar auditoria y analizar en cada arranque
if (-not (Get-ScheduledTask -TaskName "Monitor-Logins-Inicio" -TaskPath $carpetaTareas -ErrorAction SilentlyContinue)) {
$a1 = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy Bypass -WindowStyle Hidden -File `"$scriptAnalizar`""
$t1 = New-ScheduledTaskTrigger -AtStartup
Register-ScheduledTask -TaskName "Monitor-Logins-Inicio" -TaskPath $carpetaTareas -Action $a1 -Trigger $t1 -RunLevel Highest -User "SYSTEM" -Force | Out-Null
Write-Host "[OK] Tarea 'Monitor-Logins-Inicio' creada (al arrancar Windows)." -ForegroundColor Green
} else { Write-Host "[i] La tarea 'Monitor-Logins-Inicio' ya existia." -ForegroundColor Yellow }
# 8. Tarea: analizar en cada inicio de sesion
if (-not (Get-ScheduledTask -TaskName "Monitor-Logins-Logon" -TaskPath $carpetaTareas -ErrorAction SilentlyContinue)) {
$a2 = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy Bypass -WindowStyle Hidden -File `"$scriptAnalizar`""
$t2 = New-ScheduledTaskTrigger -AtLogOn
Register-ScheduledTask -TaskName "Monitor-Logins-Logon" -TaskPath $carpetaTareas -Action $a2 -Trigger $t2 -RunLevel Highest -User "SYSTEM" -Force | Out-Null
Write-Host "[OK] Tarea 'Monitor-Logins-Logon' creada (al iniciar sesion)." -ForegroundColor Green
} else { Write-Host "[i] La tarea 'Monitor-Logins-Logon' ya existia." -ForegroundColor Yellow }
# 9. Tarea: analizar cada hora
if (-not (Get-ScheduledTask -TaskName "Monitor-Logins-Horaria" -TaskPath $carpetaTareas -ErrorAction SilentlyContinue)) {
$a3 = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy Bypass -WindowStyle Hidden -File `"$scriptAnalizar`""
$t3 = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Hours 1) -RepetitionDuration (New-TimeSpan -Days 3650)
Register-ScheduledTask -TaskName "Monitor-Logins-Horaria" -TaskPath $carpetaTareas -Action $a3 -Trigger $t3 -RunLevel Highest -User "SYSTEM" -Force | Out-Null
Write-Host "[OK] Tarea 'Monitor-Logins-Horaria' creada (cada hora)." -ForegroundColor Green
} else { Write-Host "[i] La tarea 'Monitor-Logins-Horaria' ya existia." -ForegroundColor Yellow }
# 10. Verificacion final (busqueda por nombre, mas fiable que por TaskPath si el cache no esta sincronizado)
Write-Host "`n=== Tareas programadas activas ===" -ForegroundColor Cyan
Get-ScheduledTask -TaskName "Monitor-Logins-*" | Select-Object TaskName, TaskPath, State | Format-Table -AutoSize
Write-Host "[OK] Monitorizacion de logins activada y protegida con 3 tareas programadas." -ForegroundColor Green
Write-Host " Script principal: $rutaFinal" -ForegroundColor Gray
Write-Host " Script de analisis: $scriptAnalizar" -ForegroundColor Gray
Write-Host " Log: C:\Logs\monitor-logins.log" -ForegroundColor Gray
Write-Host " CSV historico: C:\Logs\monitor-logins-historico.csv" -ForegroundColor Gray
Write-Host "`n[i] Reinicia el equipo. Tras reiniciar, verifica con:" -ForegroundColor Yellow
Write-Host " Get-ScheduledTask -TaskName 'Monitor-Logins-*' | Select-Object TaskName, TaskPath, State" -ForegroundColor Gray
}
catch {
Write-Host "`n[X] Error: $($_.Exception.Message)" -ForegroundColor Red
}
finally {
Stop-Transcript | Out-Null
Read-Host "`nPulsa Enter para salir"
}🔎 Cómo verificar que la monitorización está funcionando
Tres comprobaciones para confirmar que el script está activo:
- Log de instalación:
Get-Content C:\Logs\monitor-logins.log -Tail 30debe mostrar[OK] Auditoria habilitaday[OK] Log Security ampliado. La línea[OK] Analisis completadosolo aparece tras la primera ejecución de una tarea programada (típicamente al reiniciar el equipo), no durante la instalación manual. - 3 tareas en estado Ready:
Get-ScheduledTask -TaskName "Monitor-Logins-*" | Select-Object TaskName, TaskPath, State(fiable solo después de reiniciar el equipo tras instalar) - Auditoría activa:
auditpol /get /subcategory:"{0CCE9215-69AE-11D9-BED3-505054503030}"debe mostrar Success and Failure
Si el CSV muestra AlertaFuerzaBruta = True o AlertaSpraying = True tras la primera fila de datos, investiga inmediatamente con el protocolo de respuesta.
💡 Comandos de verificación (PowerShell como administrador):
Get-Content C:\Logs\monitor-logins.log -Tail 30
Get-ScheduledTask -TaskName "Monitor-Logins-*" | Select-Object TaskName, TaskPath, State
auditpol /get /subcategory:"{0CCE9215-69AE-11D9-BED3-505054503030}"
Import-Csv C:\Logs\monitor-logins-historico.csv | Select-Object -Last 5Las 3 tareas deben estar en estado Ready. El CSV solo tendrá filas de datos después de que se dispare al menos una tarea (arranque, logon u horaria).
✅ Checklist post-instalación
Verifica estos 6 puntos para confirmar que la monitorización está activa (después de reiniciar):
- ☑ 3 tareas en estado Ready, sin duplicados, en
taskschd.msc→ SeguridadEnMiPC → Monitor-Logins - ☑
auditpol /get /subcategory:"{0CCE9215-69AE-11D9-BED3-505054503030}"muestra Success and Failure - ☑ Log Security con capacidad ≥ 200 MB
- ☑ Log en
C:\Logs\monitor-logins.logsin errores críticos - ☑ CSV en
C:\Logs\monitor-logins-historico.csvcon al menos una fila de datos - ☑ Revisas el CSV semanalmente
✔ 6/6 = monitorización activa y operativa · ✘ menos de 4 = revisar log e instalación · si las tareas no aparecen justo tras instalar, reinicia el equipo antes de dar la instalación por fallida
🚨 Protocolo de respuesta ante una alerta de la monitorización de logins en Windows
Si el CSV muestra AlertaFuerzaBruta = True o AlertaSpraying = True:
- ☑ Identifica la IP:
Get-WinEvent -FilterHashtable @{LogName='Security';Id=4625} -MaxEvents 50 | Select-Object TimeCreated, Message - ☑ Si IP externa: bloquea en firewall:
New-NetFirewallRule -DisplayName "Block IP" -Direction Inbound -RemoteAddress IP -Action Block - ☑ Si IP interna: aísla el equipo y comprueba si está comprometido
- ☑ Cambia la contraseña de la cuenta atacada desde un equipo limpio
- ☑ Comprueba si hay 4624 exitosos posteriores desde la misma IP
- ☑ Exporta evidencias:
wevtutil epl Security C:\Backup\security-$(Get-Date -f yyyyMMdd).evtx - ☑ Refuerza política de bloqueo:
net accounts /lockoutthreshold:5 /lockoutduration:30
Si la IP atacante se repite en distintas ventanas de 24 horas, un bloqueo puntual con New-NetFirewallRule no es suficiente. Consulta la guía para restringir el acceso por IP en Windows y convertir ese bloqueo reactivo en una política de firewall permanente y auditable.
⚠️ Riesgos y efectos de la monitorización de logins en Windows
| Función | ¿Afectada? | Detalle |
|---|---|---|
| Inicio de sesión local | 🟢 No | No toca cuentas ni contraseñas |
| Inicio de Windows | 🟢 No | La tarea se ejecuta en background tras el arranque |
| Banca online y web | 🟢 No | No toca DNS, hosts ni la pila de red |
| Política de auditoría | 🟡 Sí (positivo) | Se activan tres subcategorías; más eventos en el log |
| Tamaño del log Security | 🟡 Aumenta | Ampliado a 200 MB automáticamente por el script |
| Carga de CPU (3 tareas) | 🟡 Mínima | Menos de 5 segundos por ejecución; menos de 2 min/día |
🛠️ Integración de la monitorización de logins en Windows con SIEM y herramientas avanzadas
La monitorización de logins en Windows con este script cubre el análisis local; para entornos con varios equipos, conviene centralizarla en una de estas plataformas de gestión de eventos de seguridad, que agregan y correlacionan los registros de autenticación de todos los sistemas:
| Plataforma SIEM | Tipo | Coste | Ideal para |
|---|---|---|---|
| Microsoft Sentinel | Cloud (Azure) | 💰 Pago por consumo | Entornos Microsoft 365 / Azure AD |
| Splunk Enterprise Security | On-prem / Cloud | 💰💰 Comercial | Grandes empresas |
| Elastic Stack (ELK) | Open source + Enterprise | 🟢 Free / 💰 Paid | Equipos técnicos |
| Wazuh | Open source HIDS+SIEM | 🟢 100% gratis | Pymes y autoalojamiento |
| Graylog Open | Open source | 🟢 Free / 💰 Enterprise | Centralización de logs |
🛠️ Herramientas complementarias a la monitorización de logins en Windows
- 🔬 Sysmon — telemetría detallada de procesos, red y registro. Complemento esencial al log Security.
- 📊 Chainsaw — análisis rápido de .evtx con reglas Sigma preconfiguradas.
- 🔍 DeepBlueCLI — PowerShell de SANS para análisis forense del log Security.
- 📋 Hayabusa — threat hunting sobre logs .evtx con reglas Sigma.
- 📡 Windows Event Forwarding (WEF) — centralización nativa sin agentes adicionales.
- 🔐 Sigma Rules — reglas de detección traducibles a cualquier SIEM.
🆚 Sistema sin monitorización de logins en Windows vs con monitorización activa
| Característica | Sin monitorización | Con monitorización |
|---|---|---|
| Política de auditoría | 🔴 Parcialmente activa | 🟢 Logon, Special Logon y Account Lockout activas |
| Detección de fuerza bruta | 🔴 Ninguna | 🟢 Alerta automática al superar 20 fallos en 24h |
| Detección de password spraying | 🔴 Ninguna | 🟢 Alerta al detectar 5+ cuentas distintas con fallos |
| Logins en horario anómalo | 🔴 Sin distinción | 🟢 Marcados entre 00:00 y 06:00 |
| Historia para análisis | 🔴 Solo el tamaño del log | 🟢 CSV histórico ilimitado |
| Dwell time del atacante | 🔴 Semanas a meses | 🟢 Horas a días |
| Persistencia tras actualizaciones | 🔴 auditpol puede resetearse | 🟢 3 tareas reactivan la auditoría automáticamente |
🏁 Conclusión
La diferencia entre un equipo que detecta a un atacante en 24 horas y otro que tarda meses no está en el antivirus ni en el firewall: está en si alguien ha implementado la monitorización de logins en Windows o no. Activar tres subcategorías con auditpol, ampliar el log a 200 MB y dejar tres tareas programadas vigilando los cuatro Event IDs críticos cuesta diez minutos la primera vez y cero a partir de la segunda. La vigilancia de accesos es solo una capa más: complétala con la guía completa de ciberseguridad para detectar y frenar intrusiones antes de que causen daño, que abarca también malware, phishing y exposición de credenciales.
🔐 Resumen de acciones recomendadas
- ✅ Guarda el script como
monitor-logins.ps1enC:\Scriptsy ejecútalo como administrador con-File - ✅ Reinicia el equipo (obligatorio) para que el Programador de tareas sincronice las 3 tareas
- ✅ Verifica con
Get-Content C:\Logs\monitor-logins.log -Tail 30 - ✅ Confirma las 3 tareas con
Get-ScheduledTask -TaskName "Monitor-Logins-*" - ✅ Revisa el CSV histórico cada semana
- ✅ Investiga inmediatamente cualquier alerta de fuerza bruta o spraying
❓ Preguntas frecuentes
¿Qué diferencia hay entre 4624 y 4625?
👉 El 4624 registra un login exitoso; el 4625 registra un intento fallido. Ambos son necesarios para correlacionar fuerza bruta (muchos 4625) con compromiso exitoso (un 4624 tras los 4625).
¿Qué es el evento 4672 y por qué es crítico?
👉 Se dispara cuando Windows asigna privilegios especiales (SeDebugPrivilege, SeTakeOwnershipPrivilege) tras un login. Un 4672 inesperado en una cuenta normal es la firma típica de una escalación reciente.
¿Las 3 tareas ralentizan el equipo?
👉 No. Cada ejecución dura menos de 5 segundos en background como SYSTEM. La carga combinada suma menos de 2 minutos de CPU al día. La monitorización de logins en Windows con este método tiene un impacto prácticamente nulo en el rendimiento.
¿Cómo consulto las tareas programadas?
👉 PowerShell: Get-ScheduledTask -TaskName "Monitor-Logins-*" | Select-Object TaskName, TaskPath, State. GUI: Win+R → taskschd.msc → Biblioteca del Programador de tareas → SeguridadEnMiPC → Monitor-Logins.
¿Qué hago si veo una alerta de fuerza bruta?
👉 Identifica la IP con Get-WinEvent -FilterHashtable @{LogName='Security';Id=4625} -MaxEvents 50 | Select-Object TimeCreated, Message. Bloquea si es externa, aísla si es interna, y cambia la contraseña de la cuenta atacada.
¿Este script sustituye a un EDR?
👉 No. Un EDR cubre telemetría de procesos, integridad de memoria y análisis de comportamiento. La monitorización de logins en Windows con este script cubre la capa de autenticación, el punto ciego más común. Para un equipo doméstico es suficiente; para una empresa, es complementaria.
¿Cómo envío los eventos a un SIEM?
👉 Para escalar la monitorización de logins en Windows más allá de un solo equipo, la forma nativa es Windows Event Forwarding (WEF): ejecuta winrm quickconfig en el cliente y configura la suscripción con wecutil cs. Alternativamente, usa agentes como Winlogbeat (Elastic) o Splunk Universal Forwarder para reenviar el log Security a una plataforma SIEM centralizada.
Deja una respuesta