Update: An element of this solution details checking passwords online (using the Have I Been Pwned API). Troy explains succinctly in his blog-post announcing the pwned passwords list why this is a bad idea. If you are looking to implement the concept I detail in this post then WE STRONGLY recommend using a local copy of the pwned password list.
THIS POST HERE details using a local SQL Database to hold the Pwned Passwords Datasets and the change to the Management Agent to query the SQL DB instead of the HIBP API.
Troy also extended his HaveIBeenPwned API to include the ability to query as to whether a password has been pwned and is likely to be used in a brute force attack.
Microsoft provide a premium license feature in Azure Active Directory (Azure Active Directory Identity Protection) whereby leaked credential sets are checked and Admins alerted via reports. But what if you aren’t licensed for the Azure AD Premium Features, or you want something a little more customised and you have Microsoft/Forefront Identity Manager? That is what this post covers.
The following diagram looks a little more complicated than what it really is. The essence though is that password changes can come from a multitude of different scenarios. Using Microsoft’s Password Change Notification Service (PCNS) we can capture password changes and send them to Microsoft Identity Manager so that we can synchronise the password to other systems, or for this use case we can lookup to see if the users new password is on the pwned password list.
This post will cover creating the Pwned Password FIM/MIM Management Agent and flagging a boolean attribute in the MIM Service to indicate whether a users password is on the pwned password or not.
There are a few components to this solution depicted above. You will need;
- FIM/MIM Synchronisation Server
- with an Active Directory Management Agent configured (most likely you will have a Projection Rule on this MA to get your users into the Metaverse)
- not shown in the diagram above you will also need the MIM MA configured to sync users from the Metaverse to the MIM Service
- FIM/MIM Service and Portal Server (can be on the same server as above)
- Microsoft Password Change Notification Service (PCNS). This MS PFE PCNS implementation document covers it quite well and you will need;
- the PCNS AD Schema Extension installed
- the PCNS AD Password Filters installed on all your (writeable) Domain Controllers
- PCNS configured to send password changes to your FIM/MIM Sync Server
- Granfeldt PowerShell Management Agent (that we will use to check users passwords against the Have I Been Pwned pwned password API)
- Lithnet Resource Management PowerShell Module
- download it from here and install it on your FIM/MIM Server as the Pwned Password MA will use this module to populate the Pwned Password Status for users in the MIM Service
- Windows Management Framework (PowerShell) 5.x
- download it from here and install on your FIM/MIM Sync Server
Getting Started with the Granfeldt PowerShell Management Agent
If you don’t already have it go get it from here. Søren’s documentation is pretty good but does assume you have a working knowledge of FIM/MIM and this blog post is no different.
Four items of note for this solution;
- You must have an Export.ps1 file. Even though we’re not doing exports on this MA, the PS MA configuration requires a file for this field. The .ps1 doesn’t need to have any logic/script inside it. It just needs to be present
- The credentials you give the MA to run this MA are the credentials for the account that has permissions to the On Premise Active Directory where we will be importing users from to join to our Metaverse so we can pass password changes to this Management Agent
- The same account as above will also need to have permissions in the MIM Service as we will be using the account to update the new attribute we are going to create
- The path to the scripts in the PS MA Config must not contain spaces and be in old-skool 8.3 format. I’ve chosen to store my scripts in an appropriately named subdirectory under the MIM Extensions directory. Tip: from a command shell use dir /x to get the 8.3 directory format name. Mine looks like C:\PROGRA~1\MICROS~4\2010\SYNCHR~1\EXTENS~2\PwnedPWD
With the Granfeldt PowerShell Management Agent downloaded from Codeplex and installed on your FIM/MIM Server we can create our Pwned Password Management Agent.
Creating the Pwned PowerShell Management Agent
On your FIM/MIM Sync Server create a new sub-directory under your Extensions Directory. eg. PwnedPWD in C:\Program Files\Microsoft Forefront Identity Manager\2010\Synchronization Service\Extensions then create a sub-directory under PwnedPWD named Debug. C:\Program Files\Microsoft Forefront Identity Manager\2010\Synchronization Service\Extensions\PwnedPWD\Debug
Copy the following scripts (schema.ps1, import.ps1, export.ps1, password.ps1) and put them into the C:\Program Files\Microsoft Forefront Identity Manager\2010\Synchronization Service\Extensions\PwnedPWD directory
The following schema.ps1 script sets up the object class (user) and a handful of attributes from Active Diretory that will be useful for logic that we may implement in the future based on users password status.
The import.ps1 script connects to Active Directory to import our AD users into the Pwned Password Management Agent so we can join to the Metaverse object already present for users on the Active Directory Management Agent. The user needs to be joined to the Metaverse on our new MA so they are addressable as a target for PCNS.
As detailed earlier, we aren’t using an Export script in this solution.
The Password script receives password changes as they occur from Active Directory and looks up the Have I Been Pwned API to see if the new password is present on the list or not and sets a boolean attribute for the pwned password status in the MIM Service.
On your FIM/MIM Sync Server from the Synchronisation Manager select Create Management Agent from the right hand side pane. Select PowerShell from the list of Management Agents. Select Next.
Give your MA a Name and a Description. Select Next.
Provide the 8.1 style path to your Schema.ps1 script copied from the steps earlier. Provide an AD sAMAccountName and Password that also has permissions to the MIM Service as detailed in the Prerequisites. Select Next.
Provide the paths to the Import.ps1, Export.ps1 and Password.ps1 scripts copied in earlier. Select Next.
Select the user checkbox. Select Next.
Select all the attributes in the list. Select Next.
Create a Join Rule for your environment. eg. sAMAccountName => person:Accountname Select Next.
Create an import flow rule for user:pwdLastSet => person:pwdLastSet. Select Next.
Ensure that Enabled password management is selected, then select Finish.
With the Pwned Password MA created and configured we need to create at least a Stage (Full Import) and Full Sync Run Profiles and execute them to bring in the users from AD and join them to the Metaverse.
This should be something you’re already familiar with.
When running the Synchronisation we get the joins we expect. In my environment PwdLastSet was configured to sync to the MIM Service and hence the Outbound Sync to on the MIM Service MA.
MIM Service Configuration
In the MIM Service we will create a custom boolean attribute that will hold the pwned status of the users password.
Connect to your MIM Portal Server with Administrator privileges and select Schema Management from the right hand side menu.
Select All Attributes then select New
Provide an attribute name (System name) and a Display Name with a Data Type of Boolean. Provide a Description and select Finish
Search for User in Resource Types then select the User checkbox from the search results and select Binding then select New.
In the Resource Type box type User then click the validate field button (the one with the green tick). In the Attribute Type box type Pwned Password then click the validate field button (the one with the green tick). Select Finish
Configure the Active Directory MA to send passwords to the Pwned Passwords MA
On your existing Active Directory Management Agent select Properties. Select Configure Directory Partitions then under Password Synchronization enable the checkbox Enable this partition as a password synchronization source. Select Targets and select your newly created Pwned Password MA. Select Ok then Ok again.
Testing the End to End Pwned Password Check
Now you should have configured;
- PCNS including installation of the Active Directory filters
- The existing Active Directory Management Agent as a Password Source
- The existing Active Directory Management Agent to send password change events to the Pwned Password MA
Select a user in Active Directory Users and Computers, right click the user and select Reset Password.
I first provided a password I know is on the pwned list, Password1
With PCNS Logging enabled on the MIM Sync Server I can see the password event come through.
Checking in the Pwned Password MA debug log we can see in the debug logging for the user we changed the password for and that when it was checked against Have I Been Pwned the password is flagged as pwned.
Note: If you implement the solution in a production environment obviously remove the password from being logged.
In the MIM Portal search for and locate the user the password we just changed the password for.
Select the user. Scroll to the bottom and select Advanced View. Select the Extended Attributes tab. Scroll down and we can see the Pwned Password shows as checked.
Now repeating the process with a password that isn’t in the Pwned Password list. After changing the password in Active Directory Users and Computers the password went through its sync path. The log shows the password isn’t in the list.
And the MIM Portal shows the Boolean value for Pwned Password is now not selected.
Using PCNS and FIM/MIM we can check whether our Active Directory users are using passwords that aren’t in the Pwned Password list.
What we can then do if their password is in the Pwned Password list is a number of things based on what the security policy is and even what type of user it is. You’ll notice that I’ve included additional attributes in the MA that we can flow through the Metaverse and into the MIM Service that may help with some of those decisions (such as adminCount which indicates if the user is an Administrator).
Potentially for Admin users we could create a workflow in the MIM Service that forces their account to change password on next logon. For other users we could create a workflow that sends them a notification letting them know that they should change their password.
Either way, we now have visibility of the state of users passwords. Big thanks to Troy for adding Pwned Passwords to his Have I Been Pwned API.
Reiterating: An element of this solution details checking passwords online (using the Have I Been Pwned API). Troy explains succinctly in his blog-post announcing the pwned passwords list why this is a bad idea. If you are looking to implement the concept I detail in this post then WE STRONGLY recommend using a local copy of the pwned password list.