Firmar scripts PowerShell
- [Parte 1 de 2]: Hardening en la política de ejecución
- [Parte 2 de 2]: Entidad de certificación CA (ADCS), despliegue de certificado vía GPO e integridad de firma
Por motivos de seguridad Windows PowerShell establece unas políticas de ejecución de scripts. Con el fin de evitar posibles ejecuciones de scripts no deseadas. Para poder ejecutar scripts en PowerShell sin problemas, se tendrá que cambiar la política de ejecución (ExecutionPolicy). Por defecto no están definidas y vienen deshabilitadas (Restricted) para todos los scopes.
En un escenario en el que formemos parte de un dominio y deseemos ejecutar scripts PowerShell para la realización de tareas en los endpoints o servidores del parque equipos de la organización. En la mayoría de los casos me encuentro con la "solución" sencilla y poco idónea. Se trata de aplicar un GPO estableciendo la política de ejecución en modo Unrestricted en las máquinas afectadas. Esto deja vía libre a cualquier usuario para que pueda comprometer la máquina sin ningún tipo de restricción.
Aplicar un hardening en la política de ejecución de scripts PowerShell
Lo más correcto en estos casos sería aplicar esta GPO en un modo AllSigned y firmar con un certificado de confianza todos los scripts que vayan ser ejecutados aplicando así un hardening en la política de ejecución de scripts de forma que sean seguros y confiables en entornos corporativos.
Si disponemos de una PKI de una entidad de certificación ADCS (Active Directory Certificate Services) podremos generar un certificado específico para este fin y propagar este certificado a través de GPO.
Para los siguientes ejemplos usaré un certificado autofirmado.
Modos de la política de ejecución (ExecutionPolicy):
- Restricted: Bloquea todos los scripts en PowerShell y hace que todas las tareas deban ejecutarse de forma interactiva, nada automático. Es la política por defecto.
- Unrestricted: Puede ejecutar cualquier script, sin restricciones. Si se ejecuta un script sin firmar muestra una advertencia al usuario.
- RemoteSigned: Puede ejecutar scripts que han sido creados en la máquina local sin ser firmados. Pero los paquetes descargados deben estar firmados antes de poder instalarlos. Conlleva el riesgo de que no es necesario que los scripts locales vayan firmados digitalmente. Para ejecutar scripts descargados de internet (sin firmar) es necesario usar la opción Unblock-File. Es la política por defecto para Windows Server.
- AllSigned: Solo puede ejecutar paquetes y scripts firmados digitalmente por un publicador de confianza, incluidos los scripts escritos en el equipo local.
- Bypass: Similar a Unrestricted, con la diferencia de que no alerta de riesgos al usuario. Suele utilizarse en integraciones de PowerShell con otras aplicaciones, en las que funciona en una capa inferior, dado que dichas aplicaciones cuentan con un modelo de seguridad propio.
- Undefined: No se establece explícitamente ninguna de las directivas anteriores. Por defecto sería Restricted.
- Default: Establece la política de ejecución predeterminada. Restricted para clientes de Windows y RemoteSigned para Windows Server.
- MachinePolicy: Establecido por una política de grupo para todos los usuarios de la máquina.
- UserPolicy: Establecido por una política de grupo para el usuario actual de la máquina.
- Process: Afecta solo a la sesión actual de PowerShell.
- CurrentUser: Afecta solo al usuario actual.
- LocalMachine: Alcance predeterminado que afecta a todos los usuarios de la máquina.
Get-ExecutionPolicy -List
Set-ExecutionPolicy AllSigned -scope LocalMachine -Force
Figura 1: Políticas de ejecución de scripts PowerShell. |
Bypass de la política de ejecución de un solo script
En el caso de que las políticas de ejecución estén en un modo Undefined y por lo tanto es como si estuvieran en Restricted. Si queremos ejecutar un script en esa misma sesión o contexto de ejecución podemos usar el modo Bypass.
PowerShell.exe -ExecutionPolicy Bypass -File \.MyScript.ps1
También sería lo mismo.
powershell -ep Bypass .\MyScript.ps1
Figura 2: Bypass para la ejecución de un solo script. |
Firmar un script PowerShell
Referencia: Set-AuthenticodeSignature
Firmar con un certificado del almacén de certificados local
$cert = Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert
Set-AuthenticodeSignature -FilePath MyScript.ps1 -Certificate $cert
Figura 3: Firmar con un certificado del almacén local. |
Firmar un script usando un certificado de un archivo PFX
$cert = Get-PfxCertificate -FilePath C:\Certs\MySign.pfx
Set-AuthenticodeSignature -FilePath MyScript.ps1 -Certificate $cert
Figura 4: Firmar usando un un certificado .pfx. |
Agregar una firma que incluya la autoridad certificación raíz (CA)
$cert = Get-PfxCertificate -FilePath C:\Certs\MySign.pfx
Set-AuthenticodeSignature -FilePath MyScript.ps1 -Certificate $cert -IncludeChain All -TimestampServer "http://timestamp.globalsign.com/scripts/timstamp.dll"
- IncludeChain: Incluye todas las cadenas de confianza de la autoridad raíz.
- TimeStampServer: Agrega una marca de tiempo a la firma. Esto evita que el script falle cuando caduque el certificado.
Figura 4: Agregar una firma que incluya la autoridad raíz. |
Obtener información de la firma de un script firmado
Referencia: Get-AuthenticodeSignature
Get-AuthenticodeSignature .\MyScript.ps1 | Format-List *
Figura 5: Obtener información de la firma de un script firmado. |
Crear un certificado autofirmado para realizar pruebas
Referencia: New-SelfSignedCertificate
New-SelfSignedCertificate -FriendlyName "Zona System ejemplo firma de código" -CertStoreLocation Cert:\CurrentUser\My -Subject "Zona System" -Type CodeSigningCert
Figura 6: Crear certificado autofirmado para pruebas. |
Ejemplo de ejecución de script firmado
Estableciendo la política de ejecución de scripts de PowerShell en AllSigned.
Figura 7: Ejemplo de ejecución de script firmado. |
Saludos!
No hay comentarios
Publicar un comentario