Old Passwords in Use

Description

Detect active accounts with passwords that haven't been updated in more than 120 days.


Use Case

Compliance

Category

Compliance, GDPR

Security Impact

Accounts that have out-dated passwords leave an organization subject to brute force, or exposed to abuse from ex-employees. It is best practice to change passwords every ninety days for most organizations -- this search will look through Active Directory for accounts with out-of-date passwords.

Alert Volume

Medium (?)

SPL Difficulty

Basic

Journey

Stage 1

MITRE ATT&CK Tactics

Credential Access

MITRE ATT&CK Techniques

Brute Force

MITRE Threat Groups

APT3
APT33
APT41
Dragonfly 2.0
Lazarus Group
Leafminer
OilRig
Turla

Data Sources

Windows Security

   How to Implement

There are multiple approaches for pulling Active Directory data:

  • Using the Supporting Add-on for Active Directory (aka SA-ldapsearch) which provides the ldapsearch command -- recommended for on premises installations in organizations with fewer than 50,000 users (app link, docs link).
  • Using data from AD Monitor, which is the Splunk Universal Forwarder's ability to monitor Active Directory for changes -- recommended for large organizations, and for Cloud environments (doc link).
  • Using a Powershell script to query Active Directory for this data (link).

Once the data is ingested, select the search option that matches your data type, and the rest should flow smoothly. The only other consideration you may wish to employ is scheduling the search with throttling on the username, so that while you run the search daily, you don't get repeated alerts. Enterprise Security customers can leverage the suppression rules for more granular control, specifying an event-specific (and so account-specific) suppression period, but all customers can opt to only alert once per week/month/etc, to avoid duplicate alerts.

   Known False Positives

Whether this search generates false positives or not is generally dependent upon your organization's security policy. Some organizations are permissive of service accounts that have older passwords -- this is discouraged by security best practices and many auditors, but it could be permissible. The only scenario where this detection might not function as expected is when the authentication doesn't update the lastLogonTimestamp parameter in Active Directory -- this occurs most frequently for systems that don't authenticate through the standard Windows mechanism (such as Linux systems connecting to Identity Management for Unix). In that scenario, it is prudent to employ basic checks for just old passwords, ignoring the last use timestamp.

   How To Respond

When this search fires, the first thing to do is to determine based on policy whether the account with an old password is expected. If it is, add it to the account whitelist. If it is not, work with the account owner to change the password and update any systems that may be using the saved password.

   Help

Old Passwords in Use Help

This example leverages the Simple Search Assistant. Our dataset is the anonymized output of running an LDAP Search against a typical domain, pulling out a set of AD attributes. There are several ways to pull this data from live environments, including the Live Search listed below.

SPL for Old Passwords in Use

Demo Data

First we bring in our basic demo dataset, the output of the ldapsearch search command against an AD environment. We're using a macro called Load_Sample_Log_Data to wrap around | inputlookup, just so it is cleaner for the demo data.
Active Directory gives us timestamps in a couple of formats, none of which allow us to do comparisons. To solve this, we use the convert search command to convert those other time formats into Unix epoch time (a nice and clean number) that we can do math on.
This step is only required for demo data -- eval has a now() function that will tell us the current epoch time, but because we're using demo data that gets more out of date with every day that passes, we have to calculate that manually. You won't see this in the live queries.
Now we look for any accounts where the password is more than 120 days old, and the login is in the last 30 days. Why 120 days? If someone's password expires while they're on vacation, we don't want to alert, so this gives us a month of buffer. We also are filtering for only accounts that are actively used, so that we don't trigger on old disabled accounts (though that's also a worthwhile detection!).
We've got our suspect values, our last step is to format the data to be more meaningful to an analyst by converting those numeric timestamps into human-readable ones. We also clear out the unnecessary maxtime field.

Using LDAPSearch

First we run our LDAP query. This requires that you've properly configured the app, and often that you've got some basic understanding of how your Active Directory is configured. When in doubt, consult with an AD admin about where your user and service accounts are located.
Active Directory gives us timestamps in a couple of formats, none of which allow us to do comparisons. To solve this, we use the convert search command to convert those other time formats into Unix epoch time (a nice and clean number) that we can do math on.
Now we look for any accounts where the password is more than 120 days old, and the login is in the last 30 days. Why 120 days? If someone's password expires while they're on vacation, we don't want to alert, so this gives us a month of buffer. We also are filtering for only accounts that are actively used, so that we don't trigger on old disabled accounts (though that's also a worthwhile detection!).
We've got our suspect values, our last step is to format the data to be more meaningful to an analyst by converting those numeric timestamps into human-readable ones.

Using CSV File

First we bring in our basic demo dataset, the output of the ldapsearch search command against an AD environment. We're using a macro called Load_Sample_Log_Data to wrap around | inputlookup, just so it is cleaner for the demo data.
Active Directory gives us timestamps in a couple of formats, none of which allow us to do comparisons. To solve this, we use the convert search command to convert those other time formats into Unix epoch time (a nice and clean number) that we can do math on.
Now we look for any accounts where the password is more than 120 days old, and the login is in the last 30 days. Why 120 days? If someone's password expires while they're on vacation, we don't want to alert, so this gives us a month of buffer. We also are filtering for only accounts that are actively used, so that we don't trigger on old disabled accounts (though that's also a worthwhile detection!).
We've got our suspect values, our last step is to format the data to be more meaningful to an analyst by converting those numeric timestamps into human-readable ones.

Screenshot of Demo Data