Going passwordless with Window Hello for Business and SCRIL

…or SCRIL in a hybrid environment. What could possibly go wrong?

Way before the term “passwordless” was used by Microsoft to promote the use of alternative authentication methods besides a password there already was a way to go passwordless. In Active Directory there is a feature called SCRIL to achieve exactly this. SCRIL which is short for “Smart card is required for interactive logon” is an effective way to prevent any interactive sign-in to a domain joined machine using a password for the user that holds this attribute.

Regardless of what password the user is attempting to use, he will be presented with the error message:

You must use Windows Hello or a smart card to sign in.

You must use Windows Hello or a smart card to sign in.

While many companies might already have an extensive PKI and smart-card setup to support passwordless authentication on premises and with the introduction of Azure AD certificate-based authentication can use their investment as a safe way to sign-in to cloud resources as well, I would discourage anybody from implementing a new PKI just for this purpose in 2023.

A better answer might be the first option the error message refers to: Windows Hello.

Windows Hello or as it’s now called Windows Hello for Business, is another supported way to sign in besides a smart card. But how does all of this work in the background and where are the caveats especially in a hybrid environment?

The how: Kerberos authentication

The limitation or better requirement to sign in using a smart-card is not implemented on the client side, but is handled by the domain controller. As you can see in this network trace, the initial authentication request, when using a password, is blocked because of an Kerberos policy error.

Smart card logon is required and was not used.

KRB5KDC_ERR_POLICY 0xc00002fa - Smart card logon is required and was not used.

On the domain controller, this will result in a failed authentication entry in the domain controllers event log.

4771 - Kerberos pre-authentication failed.
Failure Code: 0x18 (KDC_ERR_PREAUTH_FAILED)
Pre-Authentication Type: 2 (PA-ENC-TIMESTAMP = Password authentication)

4771 - Kerberos pre-authentication failed

The user is blocked from accessing the computer or any network resource, because it never gets a successful authentication in the first place. But what changes when you use Windows Hello for Business (or a smart card)?

Windows Hello for Business

While setting up Windows Hello for Business, without realizing it, the computer you did the enrollment on will create a certificate and will act sort-of as your smart card in the future. If configured correctly, it will store the certificate used for future sign-ins in the TPM of the computer to protect it from extraction.

But before we explore this in more depth, first let’s discuss different deployment options. WHfB comes in a multitude of different of those.

  • Hybrid Azure AD Joined cloud Kerberos Trust
  • Hybrid Azure AD Joined Key Trust
  • Hybrid Azure AD Joined Certificate Trust
  • On Premises Key Trust
  • On Premises Certificate Trust

While each of them have a valid business use case, not all of them apply in a hybrid world. Both on-premises methods are not discussed further.

Hybrid Azure AD Joined cloud Kerberos Trust

This is the newest and easiest way to setup WHfB ist Cloud Kerberos Trust. In a very clever way, it uses an Kerberos TGT (correctly an partial TGT) that is provided by Azure AD as part of the Primary Refresh Token (PRT) to the end user and can be exchanged at an domain controller for a full TGT and then TGS Kerberos tickets to access all on-premises resources.

  • No PKI required whatsoever
  • Uses a partial TGT provided by Azure AD to get access to on-premises resources
  • Does not support
    • Run as
    • RDP without Remote Credential Guard or a certificate

For an in-depth exploration on who this works, read my blog post of “Windows Hello for Business Cloud Trust and KDC proxy”.

Hybrid Azure AD Joined Key Trust

In this deployment method there is no requirement for user certificates, but your domain controllers must provide a valid certificate to your endpoints. When enrolling the created public certificate is stored at user object level in Azure AD and synced to AD using Azure AD Connect

  • PKI required for Domain Controllers
  • Stores the public key used for authentication in user attribute msDS-KeyCredentialLink
  • Does not support
    • RDP without Remote Credential Guard or a certificate

Hybrid Azure AD Joined Certificate Trust

Last and least, this methods not only requires a full PKI setup for the domain controllers and the end users, but also does not support Azure AD Pass-through Authentication (PTA) or password hash sync (PHS) leaving us only with AD FS.

This is a big no no for me, so I won’t consider this option for any new deployments.

Which deployment method should I choose?

For me “Hybrid Azure AD Joined cloud Kerberos Trust” is the clear winner here. Besides the ease of deployment, this will also enable you to use FIDO2 security keys for your sign-in. This will open up the possibilities even further and enables a roaming sign-in component, because FIDO2 is not device bound like WHfB.

SCRIL and Windows Hello for Business Cloud Kerberos Trust

While having “smart card” in the name the real requirement here is a certificate for authentication, using a specific protocol in Kerberos: PKINIT.

But I hear you scream at me: Fabian, you recommended Cloud Kerberos Trust which does not use any certificates!

While this holds true, you also do not need a certificate or PKINIT in the first place. Azure AD will provide you with an partial TGS and this can be exchanged to an full TGS without sending an AS-REQ to the domain controller. Don’t believe me, let’s look at the network trace.

No AS-REQ is needed when using Windows Hello for Business Cloud Kerberos Trust

After initial sign-in the client immediately sends a TGS-REQ for the service krbtgt/DOMAINNAME and the domain controller will happily return a full TGT as part of the TGS-REP.

But what’s about packet 315 and 318 you might ask. As explained in my deep dive on this matter, this is because the client also tries to use a certificate, but this is not known to the domain controller and will be “ignored”.

So by moving the initial authentication source from on-prem AD to Azure AD we can “bypass” the need for an AS-REQ and this is where the Kerberos policy for SCRIL would have blocked us. Neat.

Security issue: Azure AD is ignoring the SCRIL based password change

While exploring SCRIL in combination with WHfB in more depth I stumbled over an very disturbing behavior:

After you enable SCRIL on-premises, the synced cloud accounts password is not changed!

While on-premises the sign-in is blocked, in the cloud the user can still use the password.

You might think, why is this an issue, SCRIL is an on-premises technology, naturally it does not have any effect on Azure AD? Let’s have a look at the documentation on passwordless strategy regarding SCIL :

When you configure a user account for SCRIL, Active Directory changes the affected user’s password to a random 128 bits of data. Additionally, domain controllers hosting the user account don’t allow the user to sign-in interactively with a password. Users will no longer need to change their password when it expires, because passwords for SCRIL users don’t expire.

This is why I expected that, after enabling the option “Smart card is required for interactive logon” on the test user, the domain controller would change the password of the user and sync the changed password to the cloud.

Enable SCRIL an a user

But when looking at the Azure AD audit log of the user, nothing changed and a sign-in to Azure AD using username and password was successful. So while the user is longer able to sign-in on-premises, in the cloud this password is still valid.

Digging a bit deeper I compared the user object on premises before and after enabling SCRIL using mimikatz. Before the user object had multiple NTLM hashes.

NTLM hashes dumped using mimikatz before the user was SCRIL enabled

After enabling SCRIL the NTLM hashes where removed and replaced with a new one. So the password is changed to a value the user is not aware of and that part of the documentation holds true.

NTLM hashes dumped using mimikatz after the user was SCRIL enabled

Still the password in Azure AD was not changed. There is also no event on the domain controller that the password had changed, but only event entries that the user attribute [userAccountControl]( changed from 512 (Normal user) to 262656 (Normal user + SMARTCARD_REQUIRED) and ms-ds-SupportedEncryptionTypes was set to 0.

Changed values by enabling SCRIL, logged by the domain controller

The change of the password hash is done somewhere in the background, not visible to anybody, even Azure AD Connect.

This seemed like a clear oversight on Microsofts part and I created a MSRC case (MSRC:VULN-087707). After about three weeks this case was closed with the following remark.

MSRC has investigated this issue and concluded that this does not pose an immediate threat that requires urgent attention that needs a change in system behavior. We have shared the report with the team responsible for maintaining the product or service. They will review for a potential fix and take appropriate action as needed to help keep customers protected.

This was in early February of 2023 using Azure AD Connect v2.116.0. Now, three months later nothing has changed in Azure AD Connect v2.1.20.0, so a fix for this seems not to be on the immediate horizon.

Of course this all is only an issue for users that are migrated to passwordless. New users will never know their password in the first place, but most environments have existing users, so there is quite a user base that is affected.

So let us explore some ways to prevent your users from using their old password to sign-in to Azure AD.

Solution and best practices

Reset the password before enabling SCRIL

When you reset the password of the user right before you enable SCRIL, this changed password will be synced to Azure AD. Since this a manual task, it’s not a reliable way in any enterprise setting, it could easily be forgotten.

Conditional Access Authentication strength

Using Conditional Access Authentication strength is a great way to limit the options a user can authenticate to Azure AD. You can scope a Conditional Access Policy to those users and require the use of specific authentication methods.

I recommend creating an authentication strength policy which only allows for passwordless methods, as well as Temporary Access Pass for onboarding and recovery.

Custom authentication strength policy

To automatically update the scope of the policy, you can create an on-prem global security group and use a PowerShell script like this to update the group membership automatically.

$SCRILGroup = Get-ADGroup "SCRIL Users"
# Remove all user from the group
$SCRILGroup | Set-ADGroup -Clear Member
# Add all users to this group
$NewMembers = Get-ADUser -Filter 'SmartcardLogonRequired -eq $true'
Add-ADGroupMember -Identity $SCRILGroup -Members $NewMembers

But Conditional Access is only evaluated after the initial sign-in, so there still is a way to use the old password, even if it does not result in an successful sign-in. So this should only be one part of the solution.

Require password change

Another part of the solution should be to require any SCRIL enabled user to change their password every day or week. What at first reading sounds like I’m a mad man, is actually a valid approach to rotate the password hash of the user on a regular basis. And even better, without any interaction of the user.

Introducing a fine grained password policy will just do that.

You must enable the option “Enable rolling of expiring NTLM secret during sign on, for users who are required to use Microsoft Passport or smart card for interactive sign on” (Microsoft Passport being Windows Hello for Business nowadays).

This feature was introduced in Windows Server 2016 and the domain level must match this version to use the feature.

Enable rolling of expiring NTLM secret during sign on, for users who are required to use Microsoft Passport or smart card for interactive sign on

Get-ADObject -filter { objectClass -eq "DomainDNS" } -Properties msDS-ExpirePasswordsOnSmartCardOnlyAccounts

Now create a fine grained password policy that will require a change of the password every so often. In this case I choose one day, which might be a bit short for your environment, since every users will change their password on a daily basis, this will add additional load to your domain controllers as well as the Azure AD Connect servers.

Next assign the password policy to the group you created earlier. This is where it’s important that it is a global security group, otherwise the FGPP won’t go into effect.

New-ADFineGrainedPasswordPolicy -Name "SCRIL Password Policy" -DisplayName "SCRIL Password Policy" -Precedence 500 -ComplexityEnabled $true -Description "Reset SCRIL users NTLM hash daily, when used." -MaxPasswordAge "1.00:00:00" -MinPasswordAge "0.00:00:00" -ReversibleEncryptionEnabled $false
Add-ADFineGrainedPasswordPolicySubject -Identity "SCRIL Password Policy" -Subjects "SCRIL Users"

At the next logon of the user using WHfB the domain controller will automatically rotate the password hash and update the attribute pwdLastSet

pwdLastSet was automatically updated

But more importantly this password change is picked up by Azure AD Connect and updated in the cloud. So this closes mentioned security issue completely.

Changed user password event in Azure AD

Disable self-service password writeback

One other important thing to keep in mind is that for those users the self-service password writeback should be disabled in Azure AD and also the on-premises Azure AD Connect account should not have the permissions to reset their password.

That way you effectively remove the possibility to reset the password from the cloud. On premises a password reset would not have any effect, as long as SCRIL is in place.

Require a TPM

Using Intune or GPO set the Windows Hello for Business setting “Use a Trusted Platform Module (TPM)” to enabled. This will prevent many attacks that require access to the private part of the certificate, which is much harder when it’s stored in an TPM.

Use a Trusted Platform Module (TPM)

Remove password credential provider

While there is the possibility to exclude the password credential provider altogether using Intune or GPO, setting “System > Logon > Exclude the following credential providers” to {60b78e88-ead8-445c-9cfd-0b87f74ea6cd}, I would not recommend doing it in production.

The downside of disabling this credential provider is, that you now can’t use a password for e.g. RunAs which would prevent you from using LAPS. This would result in users having local admin permissions by default or a big headache for your support team. And standing admin permissions are, in a security sense, much worth than showing an option on the logon screen that the user will never be able to use.

When you exclude the password credential provider it will not only be missing from the initial logon screen

Enrollment aka the elephant in the room

To bring such a solution to production one important key element must be resolved first: Enrollment.

How can the user setup Windows Hello for Business without using a password to sign-in first?

This leaves you with FIDO2 security keys for initial setup on those machine and a process that is not as smooth as I had hoped since FIDO2 security keys do not support admin based enrollment.

Onboading process for passwordless users

  1. Create the user
  2. Set the SCRIL flag
  3. Add a Temporary Access Pass as an authentication method for this user
    1. AADJ: Use TAP and WebSignIn for the initial device logon
    2. HAADJ: Let the user use the TAP to register a FIDO2 security key This must be done on another machine e.g. a secure onboarding kiosk
    3. HAADJ: The user uses the FIDO2 security key for initial device logon
  4. Setup Windows Hello for Business during initial sign-in
  5. Setup passwordless Authenticator on the users mobile device as a alternative sign-in method on all devices that currently do not support FIDO2 security keys.
  6. The user is good to go and can use WHfB from now on

In case of the AADJ scenario I also recommend to hand out a FIDO2 security key to the user. This has the benefit that the user now has a second backup method, the FIDO2 security key, should there be any trouble with WHfB and the mobile device used for passwordless Authenticator.

Azure AD joined devices

I highly recommend using a KDC proxy setup as it removes the need for direct line of sight to the domain controllers to retrieve Kerberos tickets. It sends the Kerberos packets embedded in HTTPS to the KDC proxy which will send them to the domain controller. This setup works wonderfully as long as the user has Internet access.

While I personally recommend this method, the KDC proxy is only supported by Microsoft when using RDP Gateway, Azure Virtual Desktop, Direct Access and SMB over QUIC. So please check with Microsoft before you deploy such a configuration in production.

As a fun side note: When you setup the KDC proxy you should set DisallowUnprotectedPasswordAuth to 1 to disallow the use of username and password at the edge. This way you essentially force all users that want to use the KDC proxy to go passwordless, even if they are not required on-premises yet.

The password rollover method at sign-in described earlier also works for Azure AD joined devices, as long as the user successfully requests a krbtgt from the domain controller. Using a KDC proxy will ensure this will happen even if the users is on the road and without VPN.

Potential use case

My favorite use case would be sensitive users, where you want to make sure they do not enter a password ever.

This could be administrative users, but bear those core principals in mind

  • Synced admin accounts MUST never ever hold any privileged Azure AD roles
  • They MUST be protected from password writeback to limit lateral movement paths
  • They MUST be covered by a Conditional Access Policy requiring a passwordless authentication method
  • A Conditional Access Policy requiring device compliance SHOULD be in place
  • A Conditional Access Policy using device filtering SHOULD be in place

Also since WHfB Cloud Kerberos Trust uses an Read-Only Domain Controller (RODC) computer object, you might have to modify the msDS-NeverRevealGroup property of the CN=AzureADKerberos,OU=Domain Controllers object to allow the users to even get a valid TGT.

Additional reading