Safe Password Scanner with Orchestrator, Service Manager, and PowerShell

Author by Nathan Lasnoski

I was recently given a challenge, or let's call it a "feat of engineering".  The challenge, build a password scanner that is safe and uses Service Manager and Orchestrator.  Why?  Let's say that you have a strong password policy that requires special characters, numbers, and even a length.  That means people aren't using "12345" or "Password", but it does mean they will use things like "Packers1" (if you're from Green Bay) or "BearsLost1" (if you are from Chicago).  In fact, passwords like this are pretty common in most businesses and as our services become more and more internet facing, we need to protect against our passwords being too easy to crack.  So, we were having a conversation and we thought, "how cool would it be if we used Orchestrator for this!"  So we did and it is indeed, very cool.   Here are the requirements we set for ourselves:

  • We needed a way to define what passwords to check
  • We needed to know what passwords had been checked
  • We needed to audit when the scan ran
  • We needed to make sure we didn't lock ourselves out
  • We needed to not lock out every user

  So, the solution ended up including a few key elements:  

  • Service Manager as a repository of the passwords, the state, and the scan log
  • Orchestrator as the mechanism to actually perform the scan
  • Orchestrator protects the environment from scans


Service Manager components:

We started with a custom configuration item class in Service Manager that contained the fields of the password, whether it was enabled to be checked, whether it had been checked in the past, and the date it was last checked. This was easily created with the authoring console. 0. Password We then created a custom configuration item class for the scanner log in Service Manager that contained the date of test and any log data we wanted to retain, such as the individuals who were detected as using a specific password. 1. Password Check Log  

Orchestrator components:

We start by retrieving the passwords which are enabled for testing.  We can't sort them with the initial Get Object, so we're returning the ones enabled and which haven't been checked.  We could do some more complex filters her as well. 2. Password Check Runbook All-Up   We then send the passwords into a flattened CSV instead of allowing the process to run each password independently.  This will allow us to use that CSV in an array in the next step. 2.1 Password Flatten We then take the CSV of passwords to test and take only the top one.  This looks like the following: 3. Top Password   You can see we initially create the array here:   $PasswordArray = @() $GuidArray = @()   We also use a "split" command to break the CSV into an array   $GetPassword -split "," | foreach { $PasswordArray += ,$_ } $GetGUID -split "," | foreach { $GUIDArray += ,$_ }   We then grab the array content first [0]   $Password = $PasswordArray[0] $GUID = $GUIDArray[0]   We then get the current date and format it using "Get-Date -Format s".  We could also convert it to GMT. 4. Get Date   We then mark the password as "checked" by updating the field to "true". 5. Mark Checked We then create the log that we executed a scan.  This could be extended with additional data in the future if we wanted to make our logging more sophisticated. 6. Create Log   We retrieve all of the users to check against.  In this case we are filtering out the users with "svc-", as that is our service accounts.  We could also use other fields, such as company, department, etc.  Another control would be to extend the user class and specifically test only certain users. 7. Get User We then actually take the password and test with each of the users.  It looks like this: 8. Check Password   In the script we are using a function, which needs to be at the top, then importing the Active Directory module, then running it using "$Success = Test-ADAuthentication…"  I found this script here. The actual "$Success" content is very important, since it provides the trigger as to whether or not to send an email to the user or to IT:   Function Test-ADAuthentication {   param($username,$password) (new-object directoryservices.directoryentry "",$username,$password) -ne $null }   Import-Module ActiveDirectory   $Success = Test-ADAuthentication "[DomainUsername]", "[Password]"   We then move on to sending the email.  This is accomplished with a filter. 9. Link Password   IMPORTANT.  This has the opportunity to lock out every user in your environment if you configure it wrong or don't build the appropriate tests.  The idea of this process is to now tie it to a "once per day" "Get Schedule", which would then have it test often enough to be useful, but not often enough to lock out people's accounts.  I'd say one password test per day.  I'd also start by only testing against a small subset of users to validate you're getting the results you want.   Happy scanning!   Nathan Lasnoski P.S. Thanks Ben for the idea.  :)      


Nathan Lasnoski

Chief Technology Officer