Cómo Firmar un Script de PowerShell (Y Ejecutarlo Efectivamente)

¿Necesitas asegurarte de que nadie realice modificaciones en tus scripts y los pase como originales? Si es así, entonces necesitas aprender cómo firmar scripts de PowerShell. Firmar agrega la identidad del editor al script para que los usuarios puedan decidir si confían en la fuente del script.

En este artículo, aprende cómo asegurarte de que solo se ejecuten scripts confiables en tu entorno aprendiendo cómo firmar scripts de PowerShell.

Prerrequisitos

Si vas a seguir los ejemplos de este artículo, necesitas lo siguiente.

  • A computer running on a recent version of the Windows operating system. This article uses Windows 10 version 20H2.
  • Windows PowerShell 5.1 o PowerShell 6+. Los ejemplos en este artículo utilizarán PowerShell v7.1.3.
  • A sample PowerShell script for signing. Feel free to create a script with any name and in any folder you want. This article will use a sample script called C:\ATA\myscript.ps1 that contains the code below.
Write-Host "Script Execution - OK"

Obtención de un certificado de firma de código

Antes de aprender cómo firmar un script de PowerShell, primero necesitas obtener un certificado de firma de código. En el mundo de Microsoft, los certificados de firma de código también se conocen como certificados Authenticode.

A code signing certificate is one type of digital certificate whose purpose for signing files. Signing a file or code with a code signing certificate adds proof that the file came from the publisher who signed it.

Dónde obtienes un certificado de firma de código depende de dónde planeas implementar o distribuir tus scripts firmados. Y como siempre, el costo también es un factor importante.

  • Global / Público – Necesitarás un certificado cuyo emisor sea una Autoridad de Certificación (CA) de confianza global. Ejemplos de tales CAs son GeoTrust y DigiCert. Estos certificados no son gratuitos. Por ejemplo, un certificado de Authenticode de DigiCert te costará $474 al año en el momento de escribir esto.
  • Interno / Intranet local – Si tienes un servidor de autoridad de certificación (CA) interno, puedes solicitar y descargar un certificado de firma desde tu servidor interno de CA.
  • Personal / Desarrollo – Para pruebas personales o uso en desarrollo, un certificado autofirmado debería ser suficiente. Este tipo de certificado de firma es el que usarás en este artículo.

Creación de un certificado autofirmado para firmar código

Has leído en la sección anterior que, al aprender a firmar scripts de PowerShell, primero necesitas un certificado de firma de código. Dado que solo realizarás pruebas personales en este tutorial, un certificado autofirmado sería suficiente. ¿Pero dónde lo obtienes?

Como su nombre indica, autofirmado significa que tu computadora local emitirá un certificado de firma de código para sí misma. Para generar un certificado autofirmado, sigue estos pasos.

1. Abra PowerShell como administrador en su computadora.

2. Copie el siguiente comando y ejecútelo en PowerShell. Este comando utiliza el cmdlet New-SelfSignedCertificate para crear un nuevo certificado de firma de código. El nombre del certificado es ATA Authenticode dentro del almacén de certificados personales de la computadora local.

El cmdlet New-SelfSignedCertificate solo admite la creación de certificados en el almacén de certificados personales del usuario actual (cert:\CurrentUser\My) o en el almacén de certificados personales de la máquina local (cert:\LocalMachine\My). Los certificados en cert:\LocalMachine\My están disponibles en toda la computadora.

El comando también almacena el objeto del certificado en la variable $authenticode para usarlo en el siguiente paso.

# Generar un certificado de Authenticode autofirmado en el almacén de certificados personales de la computadora local.
 $authenticode = New-SelfSignedCertificate -Subject "ATA Authenticode" -CertStoreLocation Cert:\LocalMachine\My -Type CodeSigningCert

3. A continuación, para que su computadora confíe en el nuevo certificado que ha creado, agregue el certificado autofirmado al almacén de certificados de Autoridad de Certificación Raíz de Confianza y Editor de Confianza de la computadora. Para hacerlo, copie el código a continuación y ejecútelo en PowerShell.

# Agregue el certificado de Authenticode autofirmado al almacén de certificados raíz de la computadora.
## Cree un objeto para representar el almacén de certificados LocalMachine\Root.
 $rootStore = [System.Security.Cryptography.X509Certificates.X509Store]::new("Root","LocalMachine")
## Abra el almacén de certificados raíz para lectura y escritura.
 $rootStore.Open("ReadWrite")
## Agregue el certificado almacenado en la variable $authenticode.
 $rootStore.Add($authenticode)
## Cierre el almacén de certificados raíz.
 $rootStore.Close()
 
# Agregue el certificado de Authenticode autofirmado al almacén de certificados de editores de confianza de la computadora.
## Cree un objeto para representar el almacén de certificados LocalMachine\TrustedPublisher.
 $publisherStore = [System.Security.Cryptography.X509Certificates.X509Store]::new("TrustedPublisher","LocalMachine")
## Abra el almacén de certificados de editores de confianza para lectura y escritura.
 $publisherStore.Open("ReadWrite")
## Agregue el certificado almacenado en la variable $authenticode.
 $publisherStore.Add($authenticode)
## Cierre el almacén de certificados de editores de confianza.
 $publisherStore.Close()

Hay tres razones principales para instalar los certificados autofirmados en tres almacenes de certificados diferentes.

  • El certificado que creó en el almacén de certificados Personal es el que usará como certificado de firma de código.
  • Al copiar el mismo certificado en el almacén de Publicadores de Confianza, asegura que su computadora local confíe en el publicador que firmó el script. PowerShell busca el certificado en este almacén para validar la firma de un script.
  • Finalmente, agregar el certificado autofirmado a las Autoridades de Certificación Raíz de Confianza garantiza que su computadora local confíe en los certificados almacenados en las tiendas Personal y Editoras de Confianza.

4. Para confirmar que el certificado con el asunto ATA Authenticode está en las tiendas de certificados Personal, Raíz y Editoras de Confianza, ejecute los comandos a continuación en PowerShell.

# Confirmar si el certificado Authenticode autofirmado existe en la tienda de certificados Personal de la computadora
 Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Subject -eq "CN=ATA Authenticode"}
# Confirmar si el certificado Authenticode autofirmado existe en la tienda de certificados Raíz de la computadora
 Get-ChildItem Cert:\LocalMachine\Root | Where-Object {$_.Subject -eq "CN=ATA Authenticode"}
# Confirmar si el certificado Authenticode autofirmado existe en la tienda de certificados Editoras de Confianza de la computadora
 Get-ChildItem Cert:\LocalMachine\TrustedPublisher | Where-Object {$_.Subject -eq "CN=ATA Authenticode"}
Confirming the creation of the new self-signed certificate

5. Para ver el certificado en una interfaz gráfica, abre la Consola de Certificados y busca el certificado que has creado en la carpeta Certificados dentro de las tiendas de certificados Personal, Autoridades de Certificación Raíz de Confianza, y Editoras de Confianza.

Viewing certificates in the Microsoft Management Console (MMC)

Cómo firmar scripts de PowerShell

Ahora que ha creado e instalado su certificado de firma de código en las tres tiendas de certificados, está listo para usarlo para firmar su script de PowerShell de muestra. Cuando necesite firmar scripts, el cmdlet Set-AuthenticodeSignature es la estrella principal.

Para firmar el script de PowerShell, ejecute el siguiente código en PowerShell. El primer comando obtiene el certificado de firma de código de la tienda de certificados personales de la máquina local. El segundo comando añade una firma digital al archivo del script de PowerShell.

# Obtener el certificado de firma de código de la tienda de certificados de la computadora local con el nombre *ATA Authenticode* y almacenarlo en la variable $codeCertificate.
$codeCertificate = Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Subject -eq "CN=ATA Authenticode"}

# Firmar el script de PowerShell
# PARÁMETROS:
# FilePath - Especifica la ruta del archivo del script de PowerShell que se va a firmar, por ejemplo, C:\ATA\myscript.ps1.
# Certificate - Especifica el certificado que se utilizará al firmar el script.
# TimeStampServer - Especifica el servidor de marcas de tiempo confiable que añade una marca de tiempo a la firma digital de su script. Agregar una marca de tiempo asegura que su código no caducará cuando caduque el certificado de firma.
Set-AuthenticodeSignature -FilePath C:\ATA\myscript.ps1 -Certificate $codeCertificate -TimeStampServer *<http://timestamp.digicert.com>*

La mayoría de los proveedores de certificados más confiables tienen un servidor de marca de tiempo y puedes encontrarlos en los sitios web de los proveedores. Por ejemplo, el servidor de marca de tiempo de DigiCert es http://timestamp.digicert.com y Comodo tiene http://timestamp.comodoca.com.

Después de firmar el script, deberías ver una salida similar a la captura de pantalla a continuación.

How to Sign PowerShell Scripts

Comprobando la Firma Digital de un Script de PowerShell

Hasta ahora, has firmado un script de PowerShell usando el certificado autofirmado que creaste. ¿Pero cómo sabes si el script realmente tiene una firma digital?

Abriendo el Código

Una forma de confirmar la firma digital de un script es abrirlo y ver el código en un editor de texto. Como en el ejemplo siguiente, el script firmado tiene un bloque de firma al final del código. El bloque de firma comienza con # SIG # Begin signature block y termina con # SIG # End signature block.

Viewing the digital signature in the script’s content

Eliminar el bloque de firma digital del código del script revertirá el script a no firmado.

Abriendo las Propiedades del Archivo del Script

Otra forma de verificar la firma digital del script es abrir las propiedades del archivo del script en el Explorador de Windows. Para hacerlo:

  1. En el Explorador de Windows, navega hasta la ubicación del script de PowerShell. En este ejemplo, el script está en C:\ATA\myscript.ps1.
  2. Haz clic derecho en el script y selecciona Propiedades.
  3. En la ventana de Propiedades del archivo, haz clic en la pestaña Firmas digitales, y deberías ver una firma digital en la lista de firmas.
Viewing the digital signature in the script’s file properties

Usando Get-AuthenticodeSignature

¿Te sorprendería saber que también puedes verificar la firma de un script dentro de PowerShell? Probablemente no. El cmdlet que puedes invocar para recuperar la firma de un archivo es Get-AuthenticodeSignature.

Para obtener la firma digital del script, ejecuta el siguiente comando. Este comando obtiene la firma del archivo C:\ATA\myscript.ps1. El cmdlet Select-Object -Property * muestra todos los detalles de la firma.

Get-AuthenticodeSignature -FilePath C:\\ATA\\myscript.ps1 | Select-Object -Property *

Después de ejecutar el comando, deberías ver un resultado similar al de la captura de pantalla debajo. Como puedes ver, la propiedad SignerCertificate muestra los detalles del certificado de firma. Mientras que la propiedad TimerStamperCertificate muestra el certificado del servidor de marca de tiempo.

Viewing the digital signature in PowerShell

Ejecución de un script de PowerShell firmado

En este punto, has firmado un script de PowerShell y confirmado que la firma digital está presente. Pero, la prueba definitiva de si has realizado todos los pasos correctamente es ejecutar el script y confirmar que se ejecuta.

PowerShell tiene una función de seguridad que protege a los usuarios de ejecutar scripts involuntariamente. Esta función de seguridad se llama Políticas de Ejecución. Dependiendo de la política de ejecución, PowerShell puede evitar o permitir la ejecución de scripts.

Para aprender sobre las diferentes políticas de ejecución y cómo afectan la ejecución de scripts, consulte Políticas de Ejecución de PowerShell: Comprensión y Gestión.

Para ejecutar un script de PowerShell firmado, siga estos pasos.

Primero, cambie la política de ejecución a AllSigned para asegurarse de que solo se puedan ejecutar scripts firmados. Sin hacer este paso, no puede probar con precisión si su script firmado funciona. Para hacerlo, invoque el cmdlet Set-ExecutionPolicy ejecutando el siguiente comando en PowerShell como administrador.

Set-ExecutionPolicy AllSigned

A continuación, ejecute el script de PowerShell firmado.

C:\ATA\myscript.ps1

El script debería ejecutarse sin errores ni advertencias, como puede ver en el resultado a continuación.

Running the signed script without errors

Pero, si de alguna manera el script no estaba correctamente firmado o no estaba firmado en absoluto, obtendrás un error similar al de la imagen a continuación. En tal caso, vuelve a revisar tus pasos e intenta firmar el script nuevamente.

Running a script with errors regarding the digital signature

¿Qué pasa si eventualmente actualizas tu script? ¿La firma digital seguirá siendo válida? La respuesta es no. Cualquier modificación al script firmado invalidará la firma digital del script. Ejecutar el script modificado fallará y resultará en un error.

Sigue estos pasos para probar un script firmado modificado.

1. Abre el script firmado myscript.ps1 en un editor de código o texto.

2. Modifica el código para agregar un carácter, como un guion bajo en este ejemplo. No cambies nada más.

Editing the signed script

3. Guarda el script después de modificar el código.

4. Finalmente, ejecuta el script modificado en PowerShell ejecutando el siguiente comando.

C:\ATA\myscript.ps1

Dado que has modificado el script firmado, ejecutar el script resultará en el error mostrado a continuación. Deberás firmar el script nuevamente para actualizar y corregir su firma digital.

Running a signed script with a broken digital signature

A digital signature does not guarantee that nobody modified the script from its original version. Any PowerShell script with malicious code may be digitally signed, too. Always practice caution when running scripts from sources you do not fully trust.

Conclusión

En este artículo, aprendiste por qué puede ser necesario firmar scripts de PowerShell según las políticas de ejecución. También aprendiste cómo distinguir entre un script firmado y no firmado. Finalmente, has aprendido cómo firmar scripts de PowerShell digitalmente y cómo probarlos y ejecutarlos.

Ahora que sabes cómo firmar scripts de PowerShell, ¿comenzarás a firmar scripts antes de distribuirlos o implementarlos?

Source:
https://adamtheautomator.com/how-to-sign-powershell-script/