Seguridad de PowerShell: registro, v2, CLM y JEA
PowerShell transparente y acotado: registro de bloques de script, módulos y transcripción, eliminación de la v2, CLM impuesto por App Control y JEA.
PowerShell es la capa de administración de Windows y una herramienta favorita de los atacantes, porque está presente en todas partes, ejecuta código desde memoria y puede llegar a casi cualquier API. Intentar bloquearlo suele romper las herramientas de gestión mientras los atacantes decididos encuentran otros hosts para el motor. El enfoque duradero es distinto: hacer visible cada acción de PowerShell y restringir el lenguaje disponible para el código que no es de confianza.
1. Registro de bloques de script
El registro de bloques de script guarda el contenido de cada bloque de script que procesa PowerShell, después de la desofuscación, y eso es lo que derrota a la mayoría de las cargas codificadas y ofuscadas.
- GPO: Computer Configuration > Administrative Templates > Windows Components > Windows PowerShell > Turn on PowerShell Script Block Logging = Enabled. Deje sin marcar Log script block invocation start / stop events (genera mucho ruido).
- Registro:
HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLoggingEnableScriptBlockLogging=1. - Eventos: 4104 en Applications and Services Logs > Microsoft > Windows > PowerShell > Operational. Los scripts largos se reparten en varios eventos 4104 enlazados por un identificador de bloque de script.
Incluso sin esta directiva, PowerShell 5 registra automáticamente los bloques de script que considera sospechosos como eventos 4104 de nivel advertencia. La directiva hace que el registro sea completo.
2. Registro de módulos
El registro de módulos guarda los detalles de ejecución de la canalización, incluidos los valores de los parámetros, para los módulos que elija.
- GPO: Turn on Module Logging = Enabled, nombres de módulo
*(todos los módulos). - Eventos: 4103 en el mismo registro.
Se solapa con el registro de bloques de script, pero captura valores en tiempo de ejecución (como variables expandidas dentro de un comando) que el texto del script por sí solo no muestra.
3. Transcripción
La transcripción escribe en archivos un registro de texto de la entrada y la salida de cada sesión, útil para revisar la actividad interactiva de los administradores.
- GPO: Turn on PowerShell Transcription = Enabled, directorio de salida en un recurso compartido de red de solo escritura (por ejemplo
\\logsrv\pstranscripts$), con Include invocation headers marcado. - Permisos del recurso compartido: los equipos y usuarios pueden crear archivos y escribir, pero no leer ni enumerar las transcripciones de otros; solo el equipo de seguridad puede leer.
Trate las transcripciones y los registros de bloques de script como información sensible: los administradores a veces pegan contraseñas en la consola. Si ese riesgo es relevante, Protected Event Logging (Administrative Templates > Windows Components > Event Logging > Enable Protected Event Logging) cifra el contenido del registro de eventos con un certificado para que solo su SIEM (con la clave privada) pueda leerlo.
4. Dimensionar y reenviar los registros
El registro PowerShell Operational por defecto es pequeño y se sobrescribe en pocas horas en un servidor con mucha actividad. Auméntelo y reenvíelo:
wevtutil sl "Microsoft-Windows-PowerShell/Operational" /ms:268435456 # 256 MBReenvíe los eventos 4103 y 4104 (y los 400/403 del registro clásico Windows PowerShell, que recogen el inicio y la detención del motor con la versión del host) mediante Windows Event Forwarding o su agente. Consulte la guía de directiva de auditoría y Sysmon.
5. Eliminar PowerShell 2.0
El motor de PowerShell 2.0 es anterior al registro de bloques de script, a AMSI y al modo de lenguaje restringido. Si está instalado, un atacante puede ejecutar powershell.exe -Version 2 y eludir todo lo anterior. Además depende de .NET Framework 3.5, que suele estar presente.
Get-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root
Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root -NoRestart
# Windows Server
Uninstall-WindowsFeature PowerShell-V2Microsoft eliminó PowerShell 2.0 de Windows 11 24H2 a partir de las actualizaciones de agosto de 2025 y de Windows Server 2025 a partir de septiembre de 2025; las versiones e imágenes anteriores todavía lo incluyen. Detecte los intentos de degradación mediante el evento 400 del registro Windows PowerShell con EngineVersion igual a 2.0.
6. AMSI
La Interfaz de análisis antimalware (AMSI) permite a PowerShell (y a VBScript, JScript, VBA de Office y otros) entregar el contenido del script al antivirus antes de ejecutarlo, de nuevo después de la desofuscación. Está activada por defecto con Microsoft Defender o con cualquier antivirus compatible con AMSI. Su trabajo es mantenerla así:
- Mantenga al día las actualizaciones de plataforma y de motor de Defender.
- Alerte sobre las detecciones que mencionan intentos de eludir AMSI y sobre los eventos de PowerShell que contienen patrones de elusión conocidos (por ejemplo, referencias a
AmsiUtilsoamsiInitFailed).
7. Modo de lenguaje restringido, bien impuesto
El modo de lenguaje restringido (Constrained Language Mode, CLM) elimina las partes del lenguaje de las que dependen los atacantes: tipos .NET arbitrarios, Add-Type, objetos COM fuera de una lista de permitidos y llamadas directas a la API Win32. Los cmdlets básicos siguen funcionando, así que la mayoría de los scripts de administración que se limitan a gestionar Windows se ejecutan sin problema.
Compruebe el modo actual:
$ExecutionContext.SessionState.LanguageModeLa única forma sólida de imponer CLM es el control de aplicaciones. Cuando se impone una directiva de scripts de App Control for Business (WDAC) o de AppLocker, PowerShell automáticamente:
- ejecuta en modo de lenguaje restringido las sesiones interactivas y los scripts no permitidos por la directiva;
- ejecuta en modo de lenguaje completo los scripts permitidos por la directiva (por ejemplo, firmados con su certificado interno de firma de código).
A veces se sugiere como atajo establecer la variable de entorno __PSLockdownPolicy en 4. No es un límite de seguridad: un usuario puede eliminarla. Úsela solo en un laboratorio para probar la compatibilidad de los scripts.
Firme sus scripts de administración con un certificado interno de firma de código para que conserven el lenguaje completo bajo la directiva:
$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Select-Object -First 1
Set-AuthenticodeSignature -FilePath .\Invoke-Maintenance.ps1 -Certificate $cert `
-TimestampServer "http://timestamp.digicert.com"Consulte App Control frente a AppLocker para construir la directiva en sí.
8. Just Enough Administration (JEA)
Muchas tareas del soporte técnico y de los operadores no necesitan una sesión de administrador completa. JEA expone un punto de conexión de comunicación remota de PowerShell en el que los usuarios solo pueden ejecutar comandos concretos, como una cuenta virtual temporal con los derechos necesarios, y cada comando queda transcrito.
Un ejemplo mínimo: permitir a los operadores reiniciar un servicio y consultar su estado en un servidor.
# Funcionalidad de rol: lo que puede hacer el rol
New-PSRoleCapabilityFile -Path "C:\Program Files\WindowsPowerShell\Modules\OpsJEA\RoleCapabilities\PrintOps.psrc" `
-VisibleCmdlets @{ Name = 'Restart-Service'; Parameters = @{ Name = 'Name'; ValidateSet = 'Spooler' } },
'Get-Service'
# Configuración de sesión: quién recibe qué rol, ejecución como cuenta virtual
New-PSSessionConfigurationFile -Path .\PrintOps.pssc -SessionType RestrictedRemoteServer `
-RunAsVirtualAccount -TranscriptDirectory "C:\ProgramData\JEA\Transcripts" `
-RoleDefinitions @{ 'CORP\Print-Operators' = @{ RoleCapabilities = 'PrintOps' } }
Register-PSSessionConfiguration -Name PrintOps -Path .\PrintOps.psscLos usuarios se conectan con Enter-PSSession -ComputerName srv01 -ConfigurationName PrintOps y obtienen exactamente esos dos comandos. Tenga cuidado con los cmdlets que expone: cualquiera que pueda ejecutar código arbitrario (Invoke-Expression, Start-Process sin restricciones, Add-Type) o escribir archivos en rutas arbitrarias vuelve a convertir el punto de conexión en un acceso de administrador completo.
9. El propio WinRM
- Mantenga WinRM a la escucha solo donde se necesite y limítelo con el firewall a los equipos de gestión (guía del firewall).
- No permita la autenticación básica ni el tráfico sin cifrar (Windows Components > Windows Remote Management (WinRM) > WinRM Service / Client: Allow Basic authentication = Disabled, Allow unencrypted traffic = Disabled). Son los valores por defecto; las líneas base los imponen para que no deriven.
- Deshabilite Allow CredSSP authentication salvo que un flujo de trabajo concreto lo necesite; CredSSP envía credenciales reutilizables al host remoto.
Lista de comprobación
- Registro de bloques de script (4104) y de módulos (4103) activado en todas partes
- Transcripción a un recurso compartido de solo escritura, o Protected Event Logging donde sea sensible
- Registro PowerShell Operational de 256 MB o más, reenviado
- PowerShell 2.0 eliminado; alertas sobre el evento 400 con EngineVersion 2.0
- CLM impuesto mediante App Control / AppLocker; scripts de administración firmados
- Puntos de conexión JEA para las tareas operativas delegadas
- WinRM: sin Basic, sin tráfico sin cifrar, sin CredSSP, limitado por el firewall
- Directivas de PowerShell 7 configuradas si PowerShell 7 está instalado
Con todo esto en marcha, PowerShell sigue siendo plenamente útil para los administradores, mientras que el PowerShell de un atacante queda registrado en texto claro y privado de las funciones que necesitan sus herramientas.
Preguntas frecuentes
¿Debo bloquear powershell.exe?
Normalmente no. Bloquear el ejecutable rompe la administración y los agentes de gestión, y los atacantes pueden alojar el motor de PowerShell en otros procesos. Registrarlo a fondo e imponer el modo de lenguaje restringido mediante el control de aplicaciones es mucho más eficaz.
¿La directiva de ejecución es un control de seguridad?
No. Microsoft documenta la directiva de ejecución como una función de protección contra la ejecución accidental de scripts, no como un límite de seguridad. Se puede eludir trivialmente, por ejemplo con -ExecutionPolicy Bypass. Úsela, pero no confíe en ella.
¿Estas opciones se aplican a PowerShell 7?
PowerShell 7 tiene sus propias opciones de directiva (en las plantillas administrativas de PowerShell Core que incluye PowerShell 7, o en un powershell.config.json). Puede configurarse para usar las opciones de directiva de Windows PowerShell. Configure ambas si despliega PowerShell 7.
Seguridad de PowerShell: registro, v2, CLM y JEA