Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Nivel de gravedad: Advertencia
Descripción
Esta regla identifica patrones PowerShell que están restringidos o no están permitidos en el Modo de Lenguaje Restringido (CLM).
El Modo de Lenguaje Restringido es una característica de seguridad de PowerShell que restringe:
- Tipos .NET que pueden usarse
- Objetos COM que pueden ser instanciados
- Comandos que pueden ejecutarse
- Características del lenguaje que pueden utilizarse
La CLM se utiliza comúnmente en:
- Entornos de Control de Aplicaciones (Control de Aplicaciones para Negocios, AppLocker)
- Endpoints de Administración Suficiente (JEA)
- Entornos seguros que requieren restricciones adicionales en PowerShell
Los scripts firmados digitalmente de editores de confianza se ejecutan en Modo Completo de Lenguaje (FLM) incluso en entornos CLM. La regla detecta bloques de firma (# SIG # Begin signature block) y ajusta las comprobaciones en consecuencia. La mayoría de las restricciones no se aplican a los scripts firmados, pero siempre se aplican ciertas comprobaciones (dot-sourcing, tipos de parámetros, mejores prácticas de manifiesto).
Importante
La regla realiza una comprobación sencilla de texto para bloques de firma y NO valida la autenticidad de la firma ni la confianza en el certificado. La validación real de la firma la realiza PowerShell en tiempo de ejecución.
Restricciones de modos de lenguaje restringidos
Scripts sin signo (Comprobación completa de CLM)
Los siguientes se marcan para los scripts sin firmar:
- Tipo de Adición - No se permite la compilación de código
- Objetos COM no permitidos - Solo se permiten Scripting.Dictionary, Scripting.FileSystemObject, VBScript.RegExp
- Tipos .NET prohibidos - Solo ~70 tipos permitidos (cadena, int, tabla hash, pscredential, etc.)
- Restricciones de tipo - Sobre parámetros y variables
-
Expresiones de tipo - Referencias de tipo estáticas como
[Type]::Method() - Tipos de Cast - Conversión a tipos no permitidos
- Invocaciones de miembros - Métodos/propiedades sobre tipos no permitidos
- Clases -
classPowerShell palabra clave no permitida - XAML/WPF - No permitido
- Invocar-Expresión - Restringida
- Dot-Source : puede estar restringido dependiendo del archivo que se obtenga
- Comodines del Manifesto de Módulos - No se recomienda exportar comodines
- Archivos de manifiestos de .ps1 módulo - No se permiten módulos de script que terminan en .ps1
Siempre se hace cumplir, incluso para guiones firmados
Scripts con signo (Verificación selectiva)
Para scripts con bloques de firma, solo se comprueban estos:
- Dot-sourcing
- Restricciones de tipo de parámetro
- Comodines del manifiesto del módulo (archivos .psd1)
- Módulos de script de manifiestos (archivos .psd1)
Configuración
Configuración básica
@{
Rules = @{
PSUseConstrainedLanguageMode = @{
Enable = $true
}
}
}
Parámetros
Habilitar: bool (el valor predeterminado es $false)
Habilite o deshabilite la regla durante la invocación de ScriptAnalyzer. Esta regla está deshabilitada por defecto porque no todos los scripts necesitan compatibilidad con CLM.
IgnoreSignatures: bool (El valor por defecto es $false)
Comportamiento de detección de firma de control:
-
$false(por defecto): Detectar firmas automáticamente. Los scripts firmados reciben verificación selectiva, los no firmados reciben comprobación completa. -
$true: Omitir detección de firma. TODOS los scripts reciben una verificación completa de CLM independientemente del estado de la firma.
@{
Rules = @{
PSUseConstrainedLanguageMode = @{
Enable = $true
IgnoreSignatures = $true # Enforce full CLM compliance for all scripts
}
}
}
Utilice IgnoreSignatures = $true si:
- Auditoría de scripts firmados para asegurar la compatibilidad total con CLM
- Preparación de scripts para entornos no confiables
- Aplicación estricta del cumplimiento de CLM a nivel organizacional
- Desarrollo/pruebas para ver todos los posibles problemas
Solución
Sustituir Add-Type
Utiliza cmdlets permitidos o ensamblajes de precompilación.
Reemplazar objetos COM no permitidos
Utiliza solo objetos COM permitidos (Scripting.Dictionary, Scripting.FileSystemObject, VBScript.RegExp) o los cmdlets de PowerShell.
Reemplazar tipos no permitidos
Utiliza aceleradores de tipos permitidos ([string], [int], [hashtable], etc.) o cmdlets permitidos en lugar de tipos .NET prohibidos.
Reemplazar las clases PowerShell
Úsalo New-Object PSObject con Add-Member o hashtables en lugar de clases.
Importante
[PSCustomObject]@{} la sintaxis NO está permitida en CLM porque utiliza casting de tipos.
Evita XAML
No uses WPF/XAML en scripts compatibles con CLM.
Sustituir Invoke-Expression
Utiliza ejecuciones directas (&) o alternativas más seguras.
Sustituir Dot-Sourcing
Utiliza módulos con Import-Module en lugar de usar dot sourcing cuando sea posible.
Manifiestos de módulos de corrección
- Sustituye las exportaciones comodines (
*) por listas explícitas. - Úsase
.psm1o.dllen lugar de.ps1para RootModule/NestedModules. - No use
ScriptsToProcess. Estos scripts se cargan en el ámbito del llamador y se bloquean.
Ejemplos
Ejemplo 1: Add-Type
Incorrecto
Add-Type -TypeDefinition @"
public class Helper {
public static string DoWork() { return "Done"; }
}
"@
Corregir
# Code sign your scripts/modules using proper signing tools
# (for example, Set-AuthenticodeSignature or external signing processes)
# Use allowed cmdlets instead of Add-Type-defined types where possible
# Or pre-compile, sign, and load the assembly (for example, via Add-Type -Path)
Ejemplo 2: Objetos COM
Incorrecto
$excel = New-Object -ComObject Excel.Application
Corregir
# Use allowed COM object
$dict = New-Object -ComObject Scripting.Dictionary
# Or use PowerShell cmdlets
Import-Excel -Path $file # From ImportExcel module
Ejemplo 3: Tipos prohibidos
Incorrecto
# Type constraint and member invocation flagged
function Download-File {
param([System.Net.WebClient]$Client)
$Client.DownloadString($url)
}
# Type cast and method call flagged
[System.Net.WebClient]$client = New-Object System.Net.WebClient
$data = $client.DownloadData($url)
Corregir
# Use allowed cmdlets
function Download-File {
param([string]$Url)
Invoke-WebRequest -Uri $Url
}
# Use allowed types
function Process-Text {
param([string]$Text)
$upper = $Text.ToUpper() # String methods are allowed
}
Ejemplo 4: Clases PowerShell
Incorrecto
class MyClass {
[string]$Name
[string]GetInfo() {
return $this.Name
}
}
# Also wrong - uses type cast
$obj = [PSCustomObject]@{
Name = "Test"
}
Corregir
# Option 1: New-Object PSObject with Add-Member
$obj = New-Object PSObject -Property @{
Name = "Test"
}
$obj | Add-Member -MemberType ScriptMethod -Name GetInfo -Value {
return $this.Name
}
Add-Member -InputObject $obj -NotePropertyMembers @{"Number" = 42}
# Option 2: Hashtable
$obj = @{
Name = "Test"
Number = 42
}
Ejemplo 5: Manifiestos de módulos
Incorrecto
@{
ModuleVersion = '1.0.0'
RootModule = 'MyModule.ps1' # .ps1 not recommended
FunctionsToExport = '*' # Wildcard not recommended
CmdletsToExport = '*'
}
Corregir
@{
ModuleVersion = '1.0.0'
RootModule = 'MyModule.psm1' # Use .psm1 or .dll
FunctionsToExport = @( # Explicit list
'Get-MyFunction'
'Set-MyFunction'
)
CmdletsToExport = @()
}
Ejemplo 6: Tipos de Array
Incorrecto
# Disallowed type in array
param([System.Net.WebClient[]]$Clients)
Corregir
# Allowed types in arrays are fine
param([string[]]$Names)
param([int[]]$Numbers)
param([hashtable[]]$Configuration)
Restricciones detalladas
1. Add-Type
Add-Type permite compilar código C# arbitrario y no está permitido en CLM.
Aplicado para: Solo guiones sin firmar
2. COM Objetos
Solo se permiten tres objetos COM:
Scripting.DictionaryScripting.FileSystemObjectVBScript.RegExp
Todos los demás (Excel.Application, WScript.Shell, etc.) están marcados.
Aplicado para: Solo guiones sin firmar
3. Tipos .NET
Solo permiten ~70 tipos, incluyendo:
- Primitivas:
string,int,bool,byte,char,datetime,decimal,double, etc. - Colecciones:
hashtable,array,arraylist - PowerShell:
pscredential,psobject,securestring - Servicios:
regex,guid,version,uri,xml - Arrays:
string[],int[][], etc. (array de cualquier tipo permitido)
La regla comprueba el uso de tipos en:
- Restricciones de tipo de parámetro (siempre aplicadas, incluso para scripts con signo)
- Restricciones de tipo de variable
- New-Object -TypeName
- Expresiones de tipo (
[Type]::Method()) - Tipos de fundición (
[Type]$variable) - Invocaciones de miembros en variables tipadas
Aplicado para: Restricciones de parámetros siempre; otros solo sin firmar
4. Clases PowerShell
La class palabra clave no está permitida. Úsalo New-Object PSObject con Add-Member o hashtables.
Nota:[PSCustomObject]@{} tampoco está permitido porque utiliza tipcasting.
Aplicado para: Solo guiones sin firmar
5. XAML/WPF
XAML y WPF no están permitidos en CLM.
Aplicado para: Solo guiones sin firmar
6. Invoke-Expression
Invoke-Expression está restringido en CLM.
Aplicado para: Solo guiones sin firmar
7. Dot-Sourcing
El dot-sourcing (. $PSScriptRoot\script.ps1) puede estar restringido dependiendo de la ubicación de la fuente.
Aplicado para: TODOS los guiones (sin firmar ni firmar)
8. Mejores prácticas para el manifiesto de módulos
Exportaciones comodines
No usar * en: FunctionsToExport, CmdletsToExport, AliasesToExport, VariablesToExport
Utiliza listas explícitas para seguridad y claridad.
Aplicado para: TODOS los archivos .psd1 (sin firmar ni firmar)
Archivos de módulos de script
No uses .ps1 archivos en: RootModule, ModuleToProcess, NestedModules
Úsalos .psm1 (módulos script) o .dll (módulos binarios) para mejorar el rendimiento y la compatibilidad.
Aplicado para: TODOS los archivos .psd1 (sin firmar ni firmar)