Windows PowerShellFirme aquí

Don Jones

En la columna de Windows PowerShell de enero de 2008, enfaticé la importancia de firmar digitalmente los scripts de Windows PowerShell. Y describí algunos escenarios en los que todas las directivas de ejecución excepto AllSigned podían crear vulnerabilidades de seguridad considerables en su entorno.

Algo en lo que no entré en detalle es en la forma de firmar los scripts. Puede echar un vistazo a esta columna en technetmagazine.com/issues/2008/01/PowerShell. ¿Adivina sobre lo que escribo este mes?

Más que una mera firma

La firma es el término técnico correcto para lo que estoy hablando, aunque la palabra en sí no es una buena descripción de lo que realmente sucede aquí. Firmar un script no significa que lo apruebe o autorice, como puede ser el caso con un contrato o un recibo de tarjeta de crédito. En el mundo de la seguridad digital, la firma es el proceso de adjuntar su identidad a algo y asegurarse de que el estado o la condición de ese "algo" no se ha modificado de ninguna manera. Todo se basa en la criptografía, que al menos en este caso comienza con un par de claves de cifrado.

Estas claves son conocidas como claves asimétricas porque son diferentes entre sí. El par consta de una clave privada, a la que sólo usted tiene acceso, y de una clave pública accesible por todos. Estoy simplificando esto un poco, pero básicamente cualquier cosa que se cifre con una clave privada sólo podrá descifrarse con su correspondiente clave pública.

A continuación, se describe su funcionamiento: Sigo simplificando las cosas para no interrumpir la descripción. Tengo un script de Windows PowerShell® que deseo firmar y tengo un certificado que contiene la clave privada que quiero usar para firmar el script. El propio Windows PowerShell tiene un cmdlet (que describiré en breve) que puede tomar el script y el certificado y realizar la firma. Al hacerlo, Windows PowerShell toma el script y lo cifra con mi clave privada. La copia cifrada aparece como un galimatías que se agrega a la parte inferior del script como una serie de comentarios (consulte la Figura 1). También se codifica la identidad, aunque no se cifra, en esos comentarios (la identidad se puede leer sin recurrir a la criptografía).

Figura 1 Bloque de firma almacenado en la parte inferior del script

Figura 1** Bloque de firma almacenado en la parte inferior del script **(Hacer clic en la imagen para ampliarla)

Más tarde, cuando Windows PowerShell mira la firma digital, descodifica mi identidad y la usa para obtener mi clave pública. Puesto que sólo mi clave pública puede descifrar el resto de la firma, Windows PowerShell sabe que si puede descifrar la firma es porque yo la he firmado. Si la hubiera firmado otra persona, mi clave pública no podría descifrar la firma. Una vez descifrada la firma, Windows PowerShell compara el script con la copia que se había cifrado en la firma. Si coinciden, la firma se considera intacta. Si los dos scripts difieren, la firma se rompe y se considera no válida.

Así es cómo una firma protege un script de texto no cifrado para que no se modifique sin que nadie lo advierta. Recuerde que aunque el script se puede modificar fácilmente, la firma no se puede cambiar para que coincida con el script modificado sin usar la clave privada. Y sólo yo tengo mi tecla privada.

Esto es decididamente una simplificación del proceso técnico subyacente. En la realidad, las firmas pueden contener y contienen más información, como una copia de la clave pública, información acerca de la entidad de certificación (CA) que emitió las claves, etc. Pero esta descripción ciertamente define las partes importantes del proceso y resalta el hecho de que una firma digital realmente protege su script de modificaciones no autorizadas.

Un factor esencial para la seguridad es la protección absoluta de su clave privada, ya que nunca debería acabar en otras manos. Nada más instalar su clave en Windows, debería protegerla por contraseña para que ningún proceso malintencionado pueda usar su clave sin su conocimiento. Al contener su clave privada, las tarjetas inteligentes proporcionan una seguridad aún mejor. Con una tarjeta inteligente, su clave privada nunca abandona la tarjeta. En su lugar, los datos que desea cifrar se transmiten a la tarjeta a través de su lector de hardware y el conjunto de circuitos de la propia tarjeta realiza el cifrado y devuelve los resultados.

Cómo obtener un certificado

Cmdlet del mes Export-CSV

Los participantes de los foros de PowerShellCommunity.org a menudo preguntan si Windows PowerShell puede exportar a Microsoft Excel®. ¡Por supuesto que puede! El cmdlet Export-CSV lo hace posible, ya que Excel puede abrir, editar y guardar archivos CSV de forma nativa. Por ejemplo, si desea exportar una lista de servicios, sólo tiene que ejecutar Get-Service | Export-CSV MisServicios. De hecho, puede incluir Export-CSV al final de cualquier canalización para que todos los objetos de esa canalización terminen en el archivo CSV especificado. De forma predeterminada, Export-CSV agrega una línea de encabezado a la parte superior del archivo que especifica el tipo de objeto que se ha exportado. Esta línea está comentada, así que no impide que Excel abra el archivo. Si no desea que se exporte ese tipo de información, puede agregar el parámetro -notype a Export-CSV. Además, puede agregar el parámetro -force para forzar la sobrescritura de un archivo CSV existente del mismo nombre sin pedir confirmación (el valor predeterminado es preguntar), o puede agregar el parámetro denominado -noClobber para evitar la sobrescritura de un archivo existente.

Para firmar scripts, necesitará una clase específica de certificado (un certificado de firma de código Authenticode de la clase III) y hay tres maneras principales de obtenerla. La primera es usar la infraestructura de clave pública (PKI) interna de la organización, si existe. La CA raíz de una PKI bien implementada gozará de la confianza de todos los equipos de su organización. Esto es necesario para que la organización pueda usar los certificados emitidos por la CA.

Windows Server® se comercializa con su propio software de servidor de certificados desde Windows® 2000. Puede usar este software para crear su propia PKI. Una implementación completa de PKI requiere mucha planeación, pero si necesita una PKI con el único propósito de emitir certificados de firma de código, no necesitará hacer un gran trabajo. Simplemente puede usar la directiva de grupo para pasar el certificado raíz de la CA a sus equipos para que sean de confianza.

Una segunda opción es usar una CA comercial. Una ventaja de usar una CA comercial es que, si selecciona una de las CA principales, los equipos de su organización probablemente ya estén configurados para confiar en los certificados de esa CA. Tenga en cuenta que, de forma predeterminada, Windows XP confía en un gran número de certificados, mientras que Windows Vista® confía en bastantes menos. Una CA comercial que goza de gran popularidad es VeriSign (verisign.com). Hay otras que vale la pena investigar, como CyberTrust (cybertrust.com) y Thawte (thawte.com).

La tercera opción para obtener un certificado de firma de código es hacer su propio certificado autofirmado usando una herramienta como Makecert.exe. Se comercializa con el SDK de la plataforma Windows, se instala en algunas ediciones de Microsoft® Office y se puede encontrar en muchos otros sitios. La ventaja de los certificados autofirmados es que son gratis y no requieren infraestructura. La desventaja, sin embargo, es que sólo se pueden usar en su equipo. Pero si sólo necesita habilitar la ejecución de scripts en su equipo (para pruebas o experimentos generales de firma de código) Makecert.exe es una gran opción. La documentación acerca de esta herramienta está en go.microsoft.com/fwlink/?LinkId=108538. Recuerde que han existido muchas versiones de esta herramienta a lo largo de los años, así que es posible que su equipo ejecute una versión antigua que no funcione exactamente como dice la documentación.

Una vez que se haya hecho con Makecert.exe, puede crear un certificado autofirmado mediante la ejecución de algo parecido a lo siguiente desde la línea de comandos de Windows PowerShell (y no permita que sorprenda a nadie usando cmd.exe cuando está leyendo esta columna) :

makecert -n "CN=MyRoot" -a sha1 –eku
1.3.6.1.5.5.7.3.3 -r -sv root.pvk root.cer 
–ss Root -sr localMachine

Entonces, ejecute lo siguiente:

makecert -pe -n "CN=MyCertificate" -ss MY 
–a sh1 -eku 1.3.6.1.5.5.7.3.3 -iv root.pvk 
–c root.cer

Makecert.exe le pedirá una contraseña para proteger la clave y, a continuación, creará el certificado. Puede comprobar la instalación ejecutando este código en Windows PowerShell:

gci cert:\CurrentUser\My -codesigning

Esto mostrará una lista de todos los elementos de la unidad CERT: (su almacén de certificados de Windows) que son certificados de firma de código. A propósito, todo esto está documentado también en el propio Windows PowerShell. Para encontrar esa documentación, ejecute About_Signing y lea unas cuantas pantallas.

Firma de scripts

Ahora que tiene un certificado y un script (si lo necesita para hacer pruebas, puede improvisar uno rápidamente), está listo para firmar el script. Es increíblemente fácil con Windows PowerShell. Sólo tiene que escribir:

$cert = @(gci cert:\currentuser\my
-codesigning)[0]
Set-AuthenticodeSignature myscript.ps1 $cert

La primera parte recupera el primer certificado de firma de código instalado (si tiene varios certificados instalados y quiere usar uno distinto del primero, cambie el "0" por el número apropiado). La segunda parte firma el archivo (por supuesto, tendrá que cambiar el nombre de archivo para que coincida con el suyo). ¡Es así de sencillo! Con toda franqueza, el nombre del cmdlet Set-AuthenticodeSignature me parece un poco más largo de lo necesario y por eso creé un alias llamado Sign. Ahora, puedo simplemente ejecutar:

Sign myscript.ps1 $cert

Abra el script y verá el bloque de firma insertado en la parte inferior. Trate de ejecutar el script con la directiva de ejecución establecida en AllSigned (Set-ExecutionPolicy AllSigned). Debería funcionar bien. Ahora querrá modificar el script y guardarlo, pero asegúrese de que no lo firma otra vez. Windows PowerShell debe negarse simplemente a ejecutar la versión modificada porque se ha roto la firma.

Vale la pena

¿Realmente vale la pena tanto jaleo? ¿Es pedir demasiado poder incluir en un script unas cuantas tareas administrativas sin tener que gastar 500 USB en un certificado o implementar un elemento de infraestructura completamente nuevo? Mire, yo también soy administrador y entiendo sus preocupaciones. La respuesta es que todo esto definitivamente compensa todos los esfuerzos.

Es un hecho que la seguridad casi siempre implica algún tipo de jaleo. El software antivirus puede ser una pesadez, pero no puede pasar sin él. El software de firewall es definitivamente un follón, pero como ya sabe, no es seguro ejecutar sin un firewall. Y el control de cuentas de usuario (UAC, User Account Control) de Windows Vista puede ser también un jaleo, pero aumenta la seguridad de su equipo. ¿Y no es esta seguridad mejorada lo que todos perseguimos?

Windows PowerShell es una herramienta eficaz y, como cualquier otra herramienta, siempre existe el potencial para que un usuario malintencionado la convierta en una vulnerabilidad de seguridad. Por eso es importante que adopte los pasos necesarios para anular las acciones de los usuarios malintencionados.

La firma de código es el mejor paso que puede dar y, además, no precisa mucha implicación. Por ejemplo, yo uso un editor de script gráfico que firma automáticamente mis scripts cada vez que presione Guardar, por lo que la firma de código es bastante más transparente para mí.

Puede hacerlo más transparente incluso sin un editor sofisticado. Por ejemplo, puede crear perfiles de Windows PowerShell para usted mismo (cree el archivo Microsoft.PowerShell_profile.ps1 en una carpeta denominada WindowsPowerShell localizada bajo su carpeta de documentos) y agregarle esta función:

function sign ($filename) {
  $cert = @(gci cert:\currentuser\my 
-codesigning)[0]
Set-AuthenticodeSignature $filename $cert
}

Ahora puede firmar su script escribiendo simplemente:

Sign c:\scripts\myscript.ps1

Por supuesto, ese script de perfil debe ser el primero que firme. La idea es dar unos pocos pasos para hacer la firma de scripts lo más cómoda posible y que no sea un jaleo.

Implementar una PKI de un servidor con el único propósito de emitir un certificado de firma de código no requiere mucho trabajo. Sin embargo, tenga presente que realmente necesita investigar y planear su PKI, incluidas la protección de la CA raíz y la provisión de recuperación ante desastres, especialmente si se va a usar con otros fines. Makecert.exe estará siempre disponible si usted es el único que va a ejecutar scripts en su entorno. Tenga en cuenta que el tema de ayuda de About_Signing de Windows PowerShell incluye también información acerca de cómo proteger el certificado producido por Makecert.exe.

Don Jones es el autor de Windows PowerShell: TFM y VBScript, WMI y ADSI desatados. Puede ponerse en contacto con él a través del sitio web PowerShellCommunity.org.

© 2008 Microsoft Corporation and CMP Media, LLC. Reservados todos los derechos; queda prohibida la reproducción parcial o total sin previa autorización.