Tareas Programadas de Windows
Introducción
Las tareas programadas (Scheduled Tasks) permiten ejecutar automáticamente programas o scripts según desencadenantes definidos.
Conceptos Fundamentales
Componentes de una tarea
- Desencadenante (Trigger): Cuándo se ejecuta la tarea
- Acción: Qué hace la tarea
- Condiciones: Criterios adicionales
- Parámetros: Opciones de ejecución
Tipos de desencadenantes
| Tipo | Descripción |
|---|---|
| AtStartup | Al inicio del sistema |
| AtLogOn | Al iniciar sesión un usuario |
| Once | Una sola vez |
| Daily | Diariamente |
| Weekly | Semanalmente |
| OnEvent | Ante un evento específico |
| OnIdle | Cuando el sistema está inactivo |
Gestión vía GUI
Programador de tareas (taskschd.msc)
Win+R > taskschd.msc
Estructura:
- Biblioteca del Programador de tareas
- Microsoft (tareas del sistema)
- Carpetas personalizadas
Crear una tarea básica
- Acción > Crear tarea básica
- Seguir el asistente
- Definir nombre, desencadenante, acción
Crear una tarea avanzada
- Acción > Crear tarea
- Pestaña General: Nombre, cuenta, privilegios
- Pestaña Triggers: Desencadenantes
- Pestaña Actions: Programas a ejecutar
- Pestaña Conditions: Criterios
- Pestaña Settings: Opciones
Gestión vía PowerShell
Listar las tareas
# Todas las tareas
Get-ScheduledTask
# Tareas activas
Get-ScheduledTask | Where-Object {$_.State -eq "Ready"}
# Buscar por nombre
Get-ScheduledTask -TaskName "*Update*"
# Detalles de una tarea
Get-ScheduledTask -TaskName "NomTache" | Get-ScheduledTaskInfo
Crear una tarea
# Definir la acción
$action = New-ScheduledTaskAction `
-Execute "powershell.exe" `
-Argument "-File C:\Scripts\MonScript.ps1"
# Definir el desencadenante
$trigger = New-ScheduledTaskTrigger -Daily -At "08:00"
# Definir el principal (quién ejecuta)
$principal = New-ScheduledTaskPrincipal `
-UserId "SYSTEM" `
-RunLevel Highest
# Opciones
$settings = New-ScheduledTaskSettingsSet `
-AllowStartIfOnBatteries `
-DontStopIfGoingOnBatteries
# Crear la tarea
Register-ScheduledTask `
-TaskName "MaTache" `
-Action $action `
-Trigger $trigger `
-Principal $principal `
-Settings $settings `
-Description "Description de ma tache"
Tipos de desencadenantes
# Al inicio
$trigger = New-ScheduledTaskTrigger -AtStartup
# Al iniciar sesión
$trigger = New-ScheduledTaskTrigger -AtLogOn
# Una vez
$trigger = New-ScheduledTaskTrigger -Once -At "2025-01-15 10:00"
# Diario
$trigger = New-ScheduledTaskTrigger -Daily -At "08:00"
# Semanal
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Monday -At "09:00"
# Ante un evento
$trigger = New-ScheduledTaskTrigger -AtStartup
# (para eventos específicos, usar schtasks.exe)
Modificar una tarea
# Cambiar el desencadenante
$newTrigger = New-ScheduledTaskTrigger -Daily -At "10:00"
Set-ScheduledTask -TaskName "MaTache" -Trigger $newTrigger
# Activar/Desactivar
Enable-ScheduledTask -TaskName "MaTache"
Disable-ScheduledTask -TaskName "MaTache"
Eliminar una tarea
Unregister-ScheduledTask -TaskName "MaTache" -Confirm:$false
Ejecutar manualmente
Start-ScheduledTask -TaskName "MaTache"
Gestión vía CMD
Comando SCHTASKS
:: Listar las tareas
schtasks /query
:: Detalles de una tarea
schtasks /query /tn "NomTache" /v /fo LIST
:: Crear una tarea
schtasks /create /tn "MaTache" /tr "C:\programme.exe" /sc daily /st 08:00
:: Ejecutar
schtasks /run /tn "MaTache"
:: Eliminar
schtasks /delete /tn "MaTache" /f
:: Modificar
schtasks /change /tn "MaTache" /st 10:00
Opciones comunes
/sc Schedule type (minute, hourly, daily, weekly, monthly, once, onstart, onlogon)
/st Start time (HH:MM)
/sd Start date (MM/DD/YYYY)
/ru Run as user
/rp Run as password
/rl Run level (LIMITED, HIGHEST)
Seguridad de las Tareas Programadas
Riesgos
Las tareas programadas son un vector de persistencia muy utilizado por los atacantes:
- Se ejecutan automáticamente
- Pueden tener privilegios elevados
- A menudo son ignoradas durante las auditorías
Verificaciones de seguridad
# Tareas que se ejecutan como SYSTEM
Get-ScheduledTask | ForEach-Object {
$task = $_
$principal = $task.Principal
if ($principal.UserId -eq "SYSTEM" -or $principal.UserId -like "*SYSTEM*") {
[PSCustomObject]@{
Name = $task.TaskName
Path = $task.TaskPath
User = $principal.UserId
}
}
} | Format-Table
# Tareas con ejecutables en rutas sospechosas
Get-ScheduledTask | ForEach-Object {
$actions = $_.Actions
foreach ($action in $actions) {
if ($action.Execute -like "*\Temp\*" -or
$action.Execute -like "*\AppData\*" -or
$action.Execute -like "*\Downloads\*") {
[PSCustomObject]@{
Task = $_.TaskName
Execute = $action.Execute
Arguments = $action.Arguments
}
}
}
} | Format-Table
# Tareas creadas recientemente (últimas 24h)
Get-ScheduledTask | Where-Object {
$_.Date -gt (Get-Date).AddDays(-1)
}
Indicators of Compromise (IOC)
| Indicador | Descripción |
|---|---|
| Tarea con nombre aleatorio | Posible malware |
| Ejecutable en Temp | Sospechoso |
| PowerShell codificado | Muy sospechoso |
| Tarea oculta | Técnica de evasión |
| SYSTEM ejecutando scripts de usuario | Riesgo elevado |
Hardening
- Auditar regularmente las tareas programadas
- Limitar quién puede crear tareas
- Monitorear la creación de tareas (Event ID 4698)
- Utilizar cuentas de servicio dedicadas
Persistencia vía Tareas Programadas
Técnica de ataque (a conocer para la defensa)
# Ejemplo de persistencia maliciosa (NO UTILIZAR)
# Muestra cómo proceden los atacantes
$action = New-ScheduledTaskAction `
-Execute "powershell.exe" `
-Argument "-WindowStyle Hidden -EncodedCommand <base64>"
$trigger = New-ScheduledTaskTrigger -AtStartup
Register-ScheduledTask `
-TaskName "WindowsUpdateHelper" `
-Action $action `
-Trigger $trigger `
-Principal (New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest) `
-Force
Detección
# Script de detección de tareas sospechosas
$suspicious = @()
Get-ScheduledTask | ForEach-Object {
$task = $_
$isSuspicious = $false
$reasons = @()
# Verificar las acciones
foreach ($action in $task.Actions) {
# PowerShell con comandos codificados
if ($action.Arguments -match "-[Ee]ncoded") {
$isSuspicious = $true
$reasons += "EncodedCommand"
}
# Ejecutables en rutas sospechosas
if ($action.Execute -match "\\(Temp|Downloads|AppData)\\") {
$isSuspicious = $true
$reasons += "Ruta sospechosa"
}
# Nombres que imitan servicios de Windows
if ($task.TaskName -match "^(WindowsUpdate|MicrosoftEdge|Chrome|Adobe).*\d{4,}") {
$isSuspicious = $true
$reasons += "Nombre sospechoso"
}
}
if ($isSuspicious) {
$suspicious += [PSCustomObject]@{
TaskName = $task.TaskName
TaskPath = $task.TaskPath
Raisons = ($reasons -join ", ")
}
}
}
if ($suspicious) {
Write-Host "Tareas sospechosas detectadas:" -ForegroundColor Red
$suspicious | Format-Table -AutoSize
} else {
Write-Host "No se detectaron tareas sospechosas." -ForegroundColor Green
}
Registro
Event IDs
| Event ID | Log | Descripción |
|---|---|---|
| 4698 | Security | Tarea creada |
| 4699 | Security | Tarea eliminada |
| 4700 | Security | Tarea activada |
| 4701 | Security | Tarea desactivada |
| 4702 | Security | Tarea actualizada |
| 106 | TaskScheduler/Operational | Tarea registrada |
| 140 | TaskScheduler/Operational | Tarea actualizada |
| 141 | TaskScheduler/Operational | Tarea eliminada |
| 200 | TaskScheduler/Operational | Acción iniciada |
| 201 | TaskScheduler/Operational | Acción finalizada |
Activar la auditoría
# Activar la auditoría de tareas programadas (GPO o comando)
auditpol /set /subcategory:"Other Object Access Events" /success:enable /failure:enable
Consultar los logs
# Eventos de creación de tareas
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4698
} -MaxEvents 10 | Format-Table TimeCreated, Message -Wrap
# Logs operativos
Get-WinEvent -LogName 'Microsoft-Windows-TaskScheduler/Operational' -MaxEvents 20
Ejercicios
- Cree una tarea que ejecute un script de PowerShell todos los días a las 9h
- Cree una tarea que se inicie al arrancar el sistema
- Audite las tareas existentes para identificar las sospechosas
- Consulte los logs de creación de tareas de los últimos 7 días