Firmar scripts PowerShell
Continuando con el artículo sobre como firmar scripts PowerShell estableciendo una política de ejecución AllSigned. En este post comentaré como hacer uso de las plantillas de certificados para el propósito de "Firma de código" emitidas por una Entidad de certificación CA implementada en un entorno de dominio haciendo uso del servicio ADCS (Active Directory Certificate Services), desplegando el certificado vía GPO y finalmente realizar una comprobación de integridad del script PowerShell firmado.
CA raíz y CA subordinadas
La CA raíz contiene la clave privada de toda la jerarquía de certificados, si un atacante obtuviera este certificado o emite un certificado para una entidad no autorizada, se compromete la seguridad basada en el certificado de la organización de todos los certificados que se han emitido en esa jerarquía.
Lo ideal y por seguridad sería disponer de una CA raíz que emita certificados para una CA subordinada, de modo que no se exponga directamente el primer nivel de certificado de la CA raíz, las CA subordinadas requieren una jerarquía de PKI establecida.
Entidades de certificación: empresarial e independientes
- Entidad de certificación empresarial: Deben pertenecer al dominio, se suele utilizar cuando es necesario emitir muchos certificados y aprobarlos rápidamente para un entorno de dominio Active Directory.
- Entidad de certificación independiente: Pueden pertenecer a un grupo de trabajo o a un dominio. No requieren de ADDS, se suele utilizar para emitir certificados directamente a los clientes. Dado que no tiene el certificado raíz, ofrece una mayor seguridad. La desventaja es que todos los certificados que se emiten deben ser aprobados.
Descripción del escenario para este lab
Por motivo de falta de recursos y no desplegar una CA subordinada, para estos ejemplos se hará uso únicamente de una CA raíz tipo empresarial ya implementada con el nivel de confianza máximo en la jerarquía de PKI de la organización y un equipo Windows 10 unido al dominio en el que se probará la ejecución de scripts PowerShell firmados donde se le aplicará una GPO con el certificado necesario.
Entidad de certificación CA (ADCS) y plantilla de Firma de código
Esto sería opcional pero para tener un control de permisos podemos crear un nuevo grupo en AD para este fin y asignarlo desde la consola de "Plantillas de certifiado" (certtmpl.msc) a la plantilla de que tiene como propósito la "Firma de código". De modo que todos los usuarios/grupos que formen parte del grupo añadido tengan permisos para poder solicitar esta plantilla a la entidad de certificación desde las propia consola local de administración de certificados de usuario (certmgr.msc).
Figura 1: Asignación de permisos a la plantilla de certificado "Firma de código". |
Desde la consola de "Entidad de certificación" (certsrv.msc). Emitimos la publicación de una nueva plantilla de certificado "Firma de código".
Figura 2: Emitir plantilla de certificado "Firma de código" desde una Entidad de certificación CA. |
Es el momento de solicitar un certificado para "Firma de código". Esto lo haremos desde el propio almacén de certificados de Windows (certmgr.msc) y con un usuario que tenga permisos para poder solicitar el certificado de Firma de código a la Entidad de certificación.
Figura 3: Solicitar a la CA un certificado de Firma de código. |
Una vez solicitado, exportamos el certificado en formato .cer.
Figura 4: Exportar el certificado .cer con propósitos de Firma de código. |
Despliegue de certificado vía GPO
Para que el resto de equipos del dominio dispongan del certificado .cer en su almacén de certificados, se crea una nueva GPO desde la consola de Administración de directivas de grupo (gpmc.msc).
A nivel de directiva de equipo, importamos el certificado .cer en el almacén de "Editores de confianza" (Trusted Publishers). Es importante que esté importado en este almacén, de lo contrario la ejecución de scripts PowerShell firmados en cualquier máquina unida al dominio y que tenga establecida una política de ejecución de scripts en modo AllSigned nos arrojará un mensaje de advertencia inicial (como se muestra en la Figura 7).
Figura 5: Desplegar certificado para firma de código vía GPO. |
Firmar scripts PowerShell con un certificado tipo "Firma de código"
Con el mismo usuario que hemos solicitado el certificado, firmamos un script PowerShell. Si visualizamos el fichero de script vemos que se ha incluido una firma complementaria al final del código.
Get-AuthenticodeSignature -FilePath .\MyScript.ps1$cert = Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCertSet-AuthenticodeSignature -FilePath MyScript.ps1 -Certificate $cert
Figura 6: Firmar y ejecutar script PowerShell desde el mismo usuario. |
Ejecución del script firmado en otro equipo y usuario del dominio
Probamos a ejecutar el script firmado desde otro usuario y equipo unido al dominio, en este caso un cliente Windows 10 con la política de ejecución de scripts establecida en AllSigned.
Como vemos en la siguiente captura, hay posibilidad de ejecutar el script pero nos muestra un advertencia indicando que el certificado no está importado en el almacén de "Editores de confianza" (Trusted Publishers). Por esta razón lo comentado en el punto anterior de la figura 5. De momento cancelamos la ejecución (ctrl+c).
Figura 7: Ejecutar script PowerShell desde otra máquina y usuario del dominio (sin certificado importado). |
Para importar el certificado en el almacén local de la máquina realizamos un forzado de la actualización de políticas (gpupdate /force). Una vez tenemos el certificado ya importado a través de la aplicación de la GPO creada en la Figura 5, podemos observar que al volver ejecutar el script firmado ya no se muestra ninguna advertencia.
Lógicamente si ejecutamos un script no firmado (MyScript_noSigned.ps1) se nos mostrará el mensaje de error común debido a la restricción aplicada AllSigned en la política de ejecución de scripts.
Figura 8: Ejecutar script PowerShell desde otra máquina y usuario del dominio (con certificado importado). |
Comprobación de la integridad de firma en scripts PowerShell
¿Qué pasa si se modifica el código del script firmado?
Para realizar la verificación de integridad de la firma del script se modifica el código del script firmado y se vuelve a comprobar el estado del certificado.
Si ejecutamos el script después de modificarlo se nos muestra un error indicando que "es posible que alguien no autorizado haya modificado el contenido del archivo", comprobamos nuevamente la firma del fichero y veremos un estado HashMismatch indicando claramente que se ha modificado rompiendo su integridad respecto a la firma.
Será necesario volver a firmarlo con el mismo certificado, generando así una nueva firma asignada al script.
Figura 9: Modificar script PowerShell firmado para comprobar su integridad. |
Saludos!