martes, 8 de noviembre de 2022

Azure Key Vault para tus scripts en Powershell: No more hardcored passwords...

 Estimados amigos de Inseguros !!!

En el post de hoy vamos a trabajar con algunas ideas para fortificar usuario/contraseña dentro de nuestros scripts.

Cuantos de vosotros tenéis claves a fuego en scripts?. La idea es guardarlos en un repositorio centralizado en Azure Key Vault, que nos permite más control sobre ellos.



Imagina que tu clave del usuario que hace algo en un script es mimamamemima.

La quieres cambiar cada 3 meses. En vez de cambiarla en el fichero del scrtip, yo hago una llamada el KeyVault, y me devuelve la clave.

Si la quiero cambiar, la cambio en KeyVault, pero en el script no hace falta, seguirá usando la llamada para recuperar la nueva clave. El concepto es ese más o menos.

Como siempre, voy a intentar explicaros mejor el concepto con el ejemplo. Lo primero, crear en Azure un almacen de claves e instalar el módulo de Azure en Powershell, si no lo tienes aún.


Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -Force

Connect-AzAccount

Ahora damos de alta un SPN, un service principal name, que en Azure es una aplicación que tiene una identidad concreta, y le vamos a dar una autenticación. Esta identidad será la que tenga permisos sobre el KeyVault para leer nuestra clave. 


Una vez tenemos creado el SPN, le asociamos un secreto. 


Nos vamos al almacen de claves, y le decimos que a ese SPN, le de X permisos. En este caso solo "get".
Es decir, cuando usemos nuestro script que hace "lo que sea" le pasaremos el ID y la key del paso anterior, y solo podrá recuperar secretos del KeyVault. No podrá cambiar, por ejemplo.




Ahora creamos nuestra clave, la que queremos usar en el script: mimamamemima




Como es normal, esto nos lo da porque estamos logueados en Azure. Si lo direccionamos a una variable $laclave= "chorizo" pues ya podemos usarlo.

Si no estuvieramos logueado, tendríamos que hacer algo así?


Una vez llegados a este punto, coincidireis conmigo que antes teníamos scripts con las claves, y ahora tenemos script con un secreto, que me da acceso a la clave xD xD xD. Cual es la diferencia?

Bueno, en primer lugar, hemos adquirido la buena costumbre de crearnos un usuario/clave para cada script, y un secreto en keyvault distinto. Esto ya es mucho, porque tenemos glanularidad en control de accesos, auditoria, etc, pero hablaremos en otro momento de ello. Tenemos la posibilidad de rotar estas claves, no todas, de poco en poco. También tenemos Defender for KeyVault...

Luego existe la posibilidad, de que hayamos accedido al contenido de este script, no porque tengamos una shell local con acceso al fichero, sino que hubieramos accedidor por una RFI/LFI en un server web, por lo que podríamos ver el fichero con el secreto, pero no podríamos ejecutarlo.

En el caso de máquinas en Azure, podemos establecer la IP del equipo que realiza la petición al keyvault, para no está disponible, o no se me ocurre este control, para IP on-premise.

Entonces, volvemos al asunto que nos requiere. Ahora lo que vamos a hacer es guardar el secreto que nos permite acceder al keyvault y recuperar la clave, pero lo vamos a cifrar con DPAPI. Como sabes, esto nos ayuda en el sentido de que para descifrar esa clave, debes ser el usuario que la cifro, y el sistema operativo.
Es decir, imagina el usuario kinomakino que cifra el secreto de acceso al keyvault. Para descifrarlo, tienes que ser kinomakino y estar en ese servidor. Si ejecutamos el script en ese contexto, podemos hacerlo. Si entras al servidor con otro usuario, por ejemplo administrador, no "podras" descifrar el secreto, por lo que tendrá sentido el fichero que indicamos. 

Por supuesto, este usuario que corre el script, no deberá tener permisos de login local, login interactivo, Rdp, acceso a disco ( solo a la carpeta indicada) etc... lo normal de cuando creamos un usuario para un servicio verdad? 

Con la base del script anterior, vamos a guardar en un fichero el contenido del secreto del acceso al keyvault, cifrado con dpapi:

 #$spnsecret = "Ame8Q~dAZB13s262sRzUo5k3Ipm1T5TjOJrIubFq"

#$spnsecret |  ConvertTo-Securestring -AsPlainText -Force | ConvertFrom-SecureString | Out-File "C:\sysmon_config\license.txt" 


Y ahora le decimos al script que lea de ese fichero.

 $tenant = "5790'¡0'¡90'¡90¡3d9d976e"

$spnid = "793e90'¡90'¡9bffaeadf7"

$secreto_des = Get-content "C:\sysmon_config\license.txt" | ConvertTo-SecureString

$credenciales = New-Object System.Management.Automation.PSCredential ($spnid,$secreto_des)

Connect-AzAccount -ServicePrincipal -Credential $credenciales -Tenant $tenant

$clave = Get-AzKeyVaultSecret -VaultName "formacion" -Name "miclavedescripts1" -AsPlainText

echo $clave 


Espero que haya quedada clara la idea. Usar Keyvault y sus ventajas, mediante DPAPI.

Podríamos haber usado solo DPAPI, es decir, en el script inicial, en el que "hace cosas" hacer una llamada al fichero donde tenemos cifrada , en este caso, en vez el secreto del keyvault, la propia clave, SI. Pero Keyvault aporta una capa más. Sin entrar en detalles, de esta manera, podríamos rotar la clave en Azure, y no estar volviendo a generar el fichero, por decir alguna más...

Espero que te haya ayudado, y sobre todo, aprendas de los conceptos que vamos manejando.

También podríamos hacer esto, en vez de con KeyVault, con Keep pass, como vimos aquí hace 5 años !!!

Como siempre, gracias por leerme !!!



Y si te gusta este contenido, te animo a que te registre para estar al día de nuevos post, cursos, webinars, eventos etc.