MFA everywhere! Questo è il mantra che ogni azienda dovrebbe adottare per proteggere l’accesso alle sue risorse e ai dati sensibili. Che si tratti di accesso alla posta elettronica, ai sistemi di gestione delle risorse umane, ai dati finanziari o alle applicazioni cloud, l’MFA deve esserne parte integrante ed integrata.

Tra le diverse soluzioni MFA disponibili, Microsoft Entra ID in combinazione con l’app Microsoft Authenticator è sicuramente una delle più diffuse e fornisce un’esperienza utente fluida e sicura, tanto più se supportata da adeguate Conditional Access policies.

Tuttavia, in alcuni casi è necessario o preferibile interfacciarsi direttamente con delle API per integrare la verifica MFA in processi preesistenti o sensibili. Ad oggi, Entra ID non fornisce un metodo nativo e API documentate al riguardo. Questa necessità mi ha spinto a cercare una soluzione che in modo rapido e definitivo potesse essere integrabile e facilmente accessibile per alcuni strumenti che utilizzo. Il risultato è MfaOnDemand.

MfaOnDemand

MfaOnDemand è un modulo PowerShell progettato per confermare rapidamente le identità degli utenti Entra ID tramite richieste Push da inviare a Microsoft Authenticator o anche richiedere una verifica tramite codice TOTP.

Caratteristiche degne di nota sono :

  • supporto per verifica TOTP e Push
  • pensata per l’integrazione in script e workflow preesistenti
  • autenticazione su base SecretKey e Certificati
  • non richiede nessuna Enterprise App aggiuntiva sul Tenant
  • utilizza solo API Microsoft native

Installazione

MfaOnDemand è disponibile sia su GitHub che su PowerShell Gallery

1
2
3
4
5
# Installation from local path
Import-Module .\MfaOnDemand.psd1

# Installation from PowerShell Gallery
Install-Module -Name MfaOnDemand

Utilizzo base

Per prima cosa è necessario ottenere delle credenziali valide per l’utilizzo dell’App MFA nativa di Entra ID, per fare questo bisogna registrare almeno una Key:

1
$secret = Add-MoDCredentials -Provider EntraId -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -Type Password

La Key verrà quindi usata per ogni richiesta di MfaOnDemand

1
Invoke-MoDMfa -Provider EntraId -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -Credential ($secret | ConvertTo-SecureString -AsPlainText -Force) -User [email protected] -Mode Push

Utilizzo avanzato

Come già detto, per l’utilizzo dell’App MFA nativa di Entra ID sono necessarie delle credenziali, queste possono essere sotto forma di stringa che è a tutti gli effetti una Password o in forma di Certificato di cui ovviamente dobbiamo possedere la chiave privata.
Per registrare queste credenziali MfaOnDemand fornisce una sua funzione nativa Add-MoDCredentials, utilizzabile così:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Register a new Password credential, valid for 1 day, and output as plain text
Add-MoDCredentials -Provider EntraId -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -Type Password
<#
Register a new X509 Certificate credential, valid for 1 year, and output its Thumbprint,
The certificate is stored on CurrentUser Certificates Store
#>
Add-MoDCredentials -Provider EntraId -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -Type Certificate -MyCertificate New

# Alternatively you can also register an existing X509 certificate
[X509Certificate]$cert | Add-MoDCredentials -Provider EntraId -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -Type Certificate
# or
Add-MoDCredentials -Provider EntraId -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -Type Certificate -MyCertificate <X509Certificate.Thumbprint>

La registrazione di credenziali con -Type Certificate richiede di fornire il parametro -MyCertificate avente uno di questi valori:

  • ? - Avvia un metodo interattivo che permette di scegliere un certificato tra quelli disponibili nel percorso Cert:\CurrentUser\My
  • New - Crea e registra un nuovo certificato
  • [X509Certificate] - Registra un certificato ottenuto in precedenza e che è memorizzato in una variabile di tipo [X509Certificate]
  • some_thumbprint_string - Registra un certificato presente nel percorso Cert:\CurrentUser\My utilizzando il suo Thumbprint
  • some_thumbprint_string_short - Cerca e registra un certificato presente nel percorso Cert:\CurrentUser\My utilizzando i primi 5 o più caratteri del suo Thumbprint

Per utilizzare Add-MoDCredentials è necessario autenticarsi sul Tenant Entra ID con un utente che abbia permessi Application.ReadWrite.All

entra id authentication popup

L’effettiva verifica MFA avviene tramite il comando Invoke-MoDMfa.

La prima volta che viene eseguito è necessario passare il parametro -Credential affinchè MfaOnDemand possa autenticarsi su Entra ID.
Le chiamate successive a Invoke-MoDMfa possono omettere tale parametro perchè la sessione viene mantenuta attiva in cache.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Send MFA OTP request, -Credential is a Thumbprint string from an X509Certificate stored in the CurrentUser Certificates Store (Cert:\CurrentUser\My)
Invoke-MoDMfa -Provider EntraId -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -Credential <X509Certificate.Thumbprint> -User [email protected] -Mode OTP

# Send MFA OTP request reading -Credential input from Pipeline
[X509Certificate]$cert | Invoke-MoDMfa -Provider EntraId -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -User [email protected] -Mode OTP

# Using Pipeline is also possible to register any supported credential type and feed it to Invoke-MoDMfa
Add-MoDCredentials -Provider EntraId -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -Type Certificate -MyCertificate New | Invoke-MoDMfa -Provider EntraId -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -User [email protected] -Mode OTP
# or
Add-MoDCredentials -Provider EntraId -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -Type Password | ConvertTo-SecureString -AsPlainText -Force | Invoke-MoDMfa -Provider EntraId -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -User [email protected] -Mode OTP

In figura vengono mostrati alcuni possibili utilizzi e output di MfaOnDemand

Entra ID MfaOnDemand output

MfaOnDemand fornisce anche un’altra funzione nativa per un facile recupero delle credenziali precedentemente registrate su Entra ID: Get-MoDCredentials

1
2
# Output both Passwords and Certificates
Get-MoDCredentials -Provider EntraId -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Entra ID MfaOnDemand credentials

Note

L’uso di Password è considerato meno sicuro rispetto a Certificate, per tale motivo le credenziali aggiunte tramite Add-MoDCredentials -Type Password hanno validità di sole 24 ore mentre quelle aggiunte tramite Add-MoDCredentials -Type Certificate hanno una validità di 365 giorni.

MfaOnDemand non gestisce la pulizia delle credenziali registrate tramite Add-MoDCredentials. Effettuate una puntuale e periodica pulizia delle credenziali, sia di quelle scadute che di quelle non più in uso.
Per semplificare la pulizia Get-MoDCredentials mostra anche i comandi per la rimozione delle Key esistenti, usateli con cautela!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Output both Passwords and Certificates
Get-MoDCredentials -Provider EntraId -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
...
#----- USE WITH CAUTION -----
$keyId = '<KeyId>'
#** Command for password removal
    Connect-MgGraph -NoWelcome -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -Scopes 'Application.ReadWrite.All'; Remove-MgServicePrincipalPassword -ServicePrincipalId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -KeyId $keyId

#** Command for certificate removal
    Connect-MgGraph -NoWelcome -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -Scopes 'Application.ReadWrite.All'; $keyCreds=(Get-MgServicePrincipal -ServicePrincipalId 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx').KeyCredentials; Update-MgServicePrincipal -ServicePrincipalId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -KeyCredentials ($keyCreds|Where-Object { $_.KeyId -ne $keyId }) -Confirm

Invoke-MoDMfa -Credential <password> accetta in input solo SecureString, l’output di Add-MoDCredentials -Type Password è invece plain text e deve quindi essere convertito tramite ConvertTo-SecureString.

La verifica tramite Number Matching di Microsoft Authenticator non è supportata.

Disclaimer

MfaOnDemand è (spero) uno strumento che può essere utile e molto versatile, è importante però sottolineare un paio di riflessioni da tenere in debita considerazione.
Primo, MFA fatigue è un problema vero e riscontrabile, per quanto possibile non è il caso di eccedere nelle verifiche MFA e nel caso è preferibile utilizzare -Mode OTP.
Secondo, potenzialmente legato al primo, MfaOnDemand utilizza API non documentate ed è facile pensare che Microsoft abbia fatto questa scelta per un buon motivo quindi meglio non abusarne.

Sviluppi futuri

Tempo e risorse permettendo sarebbe interessante ampliare il progetto ed eventualmente aggiungere ulteriori Provider oltre ad Entra ID, se quindi avete casi d’uso o fornitori di servizi MFA che vorreste fossero implementati fatemelo sapere nei commenti o su GitHub