Smart Card Logon Enforcement - Long Edition!

Hey everyone - it's been a while since the last post with so much going on in IT; the boom of the cloud, security breaches/incidents, new products, etc.  Wanted to take a little time to talk about something that hit my desk again recently and most folks in the DoD and other spaces wind up doing at some point,  and usually various iterations of it across multiple networks.  You may be looking to give it a go for the first time or maybe you're looking at making some changes in how you skin this cat?  There are some choices and things to be aware of when you start considering how you process enforcement of smart card logon (SCL).  First I'll start out by talking about how you can go about requiring that a smart card be used for "interactive logon," which is logon type 2.  Logon types are important when you start talking about SCL enforcement and enablement which are two distinctly different things, more on that later.  SCL enforcement can be accomplished in one of two ways, by the individual machine via local security policy, or configured per user.

 

COA 1 - Enforce SCL using a local security policy setting

This option is enforced by group policy application to the machine, AKA "machine based enforcement."  The setting "Interactive logon: Require smart card" is exposed in an ADMX template:

Computer Configuration\Windows Settings\Security Settings\Local Policies\Security Options

 

Make it so!

Ok, we applied the policy.  First up is management, once this policy is applied to a workstation no one will be able to login to it with anything but a smart card.  Ever.  Until you remove the policy setting.  It makes for a high touch scenario where you are constantly changing the application of this setting by moving workstations in the directory or filtering the GPO on them somehow.  With the constant flux of new users with no smartcard,  existing users forgetting their smart card at home, or worse yet losing the smart card; this can make for a cumbersome job for IT Pros to manage.  Tracking what machines should be enforced, what machines shouldn't, and when they should be reverted one way or the other can turn into quite the affair.  Also consider the scenario of users moving around the building or campus, if I lost my smart card, dog ate it, or whatever the case may be I can't just login to any workstation without a call to the help desk or IT shop.  Something else to add to what I'm sure is a long list of daily activities.  : (

How are we doing?

Then there's reporting, how do we report to information assurance managers how many users are actually SCL enforced?  Well the simple answer is, you can't - because you're enforcing machines not users.  Sure you can scrape DC security logs (oh boy, lets hope you have some type of audit collection services) and get an idea of how many smart card logons are happening, but this too can become inconsistent with so many variables and scenarios to account for.  Potentially what you end up reporting is the number of machines that are enforced, the number that aren't, how many smart card logons are happening across all DCs in the domain, and how many un/pw logons are happening.  It would be quite interesting trying to get an accurate count of how many people "are required" to use a smart card for interactive logon with all of this data.  Not so much fun, I'd much rather be playing Halo 5.

That pesky password again!

Let's not forget about the subject of  password management either.  If you aren't enforcing SCL on the user account control attribute on the user account object in AD, then passwords can still be used.  As long as a user knows their current password, they can continue to change it.  They can also continue to use it on machines that do not have the require smart card policy enforced.  In fact they can also continue to use the password on machines where smart card logon is required for interactive logon (type 2) for authenticating to network resources, which are "logon type 3."  So what you can potentially end up with is a hybrid mesh of users and computers in various states, some users may have their password reset because they forgot their smart card, then they can continue to change it and use it even after they have their machine "re-enforced" to require smart card logon.  They can still use the password on machines that aren't SCL enforced (if they find one), and they can still use the password for Network logons, which are "Type 3" logons.

Thoughts?

For these reasons this is my least favorite of the two ways to accomplish SCL enforcement.  It's not very flexible, agile, or hands off from an administrative perspective.  I'm not saying enforcing SCL this way doesn't have its places, for instance maybe a medium or high assurance kiosk type workstation such as a local registration authority machine, or other sensitive kiosk type.  But generally speaking for most cases I tend to recommend against this method.

 

COA 2 - Enforce SCL on the AD User Account Object

Alternatively smart card logon can also be enforced on a per-user basis by modifying the "Smart Card Required for Interactive Logon" (AKA SCRIL) user account control flag on the AD user object.  The user account control attribute is a single user account object attribute that is composed of bitmask flags.   This attribute value can be a combination of one or more of 24 possible values.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

The flag we're interested in is ADS_UF_SMARTCARD_REQUIRED which has a value of 262144.  We can programmatically test for this flag (a number of ways) to very quickly determine if a user is SCL enforced or not, and based on this information perform some action.  The flag corresponds to this checkbox in the UI:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

It's important to understand what happens when you toggle this flag on with a bitwise operation.  It sets the password to a high entropy 120 character random value, so that the user does not know the password.  This password hash can be scrambled at will, by - you guessed it flipping the flag off and then flipping it back on, this is commonly referred to as "Rotating the password hash."  As you may or may not know password hashes for SCL enforced accounts should be rotated at an interval since the hashes never technically expire and can be stolen and used for logons other than type 2 (interactive), of which logon type 3 (network) is probably the scariest and likely one of (if not the) the most widely used logon types by an attacker when they're traversing network endpoints.  There is also something here that some folks are not aware of.  After you've toggled the flag on, SCL enforced the account and thereby scrambled the password - an administrator can in fact reset the users password for them and they can use it for network logons (Type 3)!  This is where the terms "SCL Enablement," and SCL Enforcement" come into play.  There are really 3 configurations a user can potentially be in when using smart cards:

  1. SCL Enabled (here we are only talking about implicit UPN mapping)
    1. Subject Alternative Name - Principal name on the smart card certificate is implicitly mapped to an AD user objects UPN attribute
  2. SCL Enforced
    1. Subject Alternative Name - Principal name on the smart card certificate is implicitly mapped to an AD user objects UPN attribute
    2. SCRIL flag ON
  3. SCL Enforced and has/knows password
    1. Subject Alternative Name - Principal name on the smart card certificate is implicitly mapped to an AD user objects UPN attribute
    2. SCRIL flag ON
    3. Admin resets password, user knows and can maintain password (pw can be used for type 3 logons)

The ideal place to be from a security perspective is number 2, with the hash being scrambled at an interval.  Number 3 could happen (I've seen it) in an environment if there is a non-smart card aware application or service that a user must be able to logon to remotely (type 3) AND they must be SCL enforced.  This scenario doesn't happen often, but it can happen.  Number 1 is exactly that, you are enabled for smart card logon you can use it or not use it.  Scenarios 1 and 3 are considered less desirable due to the fact that the user has/knows a password and therefore a hash that can potentially be a victim of credential theft.

Make it so, but faster, stronger, leaner!

So we can toggle this flag to SCL enforce users, awesome.  There are a bunch of ways we can do this in both vbscript and PowerShell.  Hopefully everyone is using PowerShell these days since its the administrative tool of choice, so we'll go with that.  We can use some code to perform pretty basic stuff, like the following:

  1. Query the directory for users who are NOT SCRIL enforced
  2. Enforce them

But we likely want to do something like the following:

  1. Query the directory for users
  2. Check if they are SCRIL or Not
    1. If they are NOT SCRIL
      1. Check if they are an exception and if so Skip
      2. If they are not an exception toggle the SCRIL flag on
    2. If they are already SCRIL
      1. Toggle SCRIL flag off, then toggle back ON to scramble hash

You'll probably want to use some attribute on the user object to key off of to tell if a user is an exception to smart card logon enforcement or not.  Group membership in an exception group seems to be the most widely used and easiest to implement.  Identify your exception groups, write your PowerShell code and schedule it to run at an interval.  I like the idea of running it nightly for a few reasons.  First being your password hashes on already SCL enforced accounts will be scrambled nightly thus only giving those hashes a glorious 24 hour life.  The second is for ease of un-enforcement.  Consider the following scenario:

  1. User forgets smart card at home.
  2. User calls help desk, account gets un-enforced and password gets reset.
  3. User works all day, then goes home.
  4. That night the scheduled enforcement task runs and because the user is not a member of an exception group they are again enforced.

Hopefully they remember their smart card the next day, otherwise rinse and repeat.  Users should only be placed in SCL exception security groups for long term exceptions.  You are not managing/filtering GPOs, moving machines, hunting for an un-enforced machine to logon to, etc.  You simply un-enforce the account and reset the password for the user, the nightly job takes care of the rest.  The user also has the flexibility to roam the building/campus and logon at any workstation.  You can also choose to rotate the password hashes or not of already enforced users during the nightly job.

Oh and don't forget to use a least privileged service account for the identity that the script runs under, in the directory all you need is an account that has Read Account Restrictions, and Write Account restrictions against the user objects it needs to process delegated to it.  ; )  On the server you run it from you need the logon as a batch user rights assignment for the identity.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Here is a small snip of PowerShell that goes over this basic concept.  You'll want to add all of the standard stuff like logging, error handling, modify your queries, modify/add your exception groups, etc.  You get the idea!

 

 Import-Module ActiveDirectory

#query AD for user accounts using the following LDAP filter (All user accounts in the Department users OU)
$OUQuery1 = Get-ADObject -LDAPFilter "(&(ObjectCategory=Person)(ObjectClass=User))" -Properties distinguishedName,useraccountcontrol -server localhost:389 -searchBase "ou=department users,dc=proseware,dc=com" -searchScope subtree

function Enforce-Users($Users)
{
    #here we test the $users variable to ensure it isn't NULL"
    if($users)
    {
        #do work here, iterate through the $users variable (Get-ADObject query return set)
        foreach($user in $users)
        {
            $exception = "False" 
            #test for a clo exception group, only searches one level - not recursively, if you want a recursive dig add your code here
            $userGroupMemberships = Get-ADPrincipalGroupMembership -server localhost:389 -identity $user.distinguishedName
            foreach($groupmembership in $userGroupMemberships)
            {
                if($groupmembership -like "*PROAZURE_CLO_Exceptions*")
                {
                    Write-Host "Not Enforced: " $user.name
                    $exception = "True"
                }
            }
            if($exception -eq "False")
            {
                #not an exception, enforce smart card required for interactive logon
                $UACValue = $user.userAccountControl
                #check account to see if it is currently enforced
                if($UACValue -band 262144)
                {
                    #Account is currently enforced, unenforce and re-enforce to scramble password
                    $user.userAccountControl = $user.userAccountControl -bxor 262144
                    Set-ADObject -Instance $user
                    $user.userAccountControl = $user.userAccountControl -bor 262144
                    Set-ADObject -Instance $user 
                    Write-Host "Enforced: " $user.name
                }
                else
                {
                    #Account is NOT currently enforced, enforce account
                    $user.userAccountControl = $user.userAccountControl -bor 262144
                    Set-ADObject -Instance $user 
                    write-host "Enforced: " $user.name
                }
            }  
        }
    }
}

Enforce-Users($OUQuery1)

How are we doing now?

How many users are SCL enforced?  Lets see, its right at your fingertips with some LDAP filters; no admin account needed.  Scope your queries to your specific OUs and you'll have the information quickly and easily.  Return any attributes you like, export to CSV, dump to text file, etc.  Tons of options here.  Create a graphical report using PowerBI maybe!?

To return all user account objects that are SCL enforced:

dsquery * -filter "(&(ObjectCategory=Person)(ObjectClass=User)(userAccountControl:1.2.840.113556.1.4.803:=262144))" name userPrincipalName distinguishedName

To return all users account objects that are NOT SCL enforced:

dsquery * -filter "(&(ObjectCategory=Person)(ObjectClass=User)(!userAccountControl:1.2.840.113556.1.4.803:=262144))" name userPrincipalName distinguishedName

As you can see reporting is fairly easy and super flexible, you can query the directory with dsquery, vbscript, PowerShell, the MMC snap-in, etc!

That pesky password? Gone!

It's a constant game of cat and mouse to attempt to eliminate the use of passwords altogether.  But hey if we are smart card enforcing users and rotating their password hashes at an (hopefully short) interval then we are in good shape!  Audit your enforcement exception security groups regularly - the less users that have/know their password the better.

Thoughts?

Utilizing a PowerShell script to perform the workload of processing user accounts for enforcement allows for completely automated execution of the task, granular targeting by organizational unit, and expected consistency of results.  For ease of administration, reporting, consistency, and greater flexibility the user account control (UAC) attribute on AD user account objects is the recommended way to smart card enforce users (in most cases).

Happy Friday!

Jesse