Compromised credentials
Guidance from our computer security incident response team (CSIRT) when responding to compromised credential notifications.
Jisc is alerted to compromised credential data sets from a vast range of different sources. (eg law enforcement tipoffs, paste bins, dark web marketplaces, etc.) When we discover or are made aware of recent compromised credential data relating to our members, we aim to notify the impacted member ASAP and with as much supporting context as possible as to the source and authenticity of the data. However, it is often common that we are unable to validate the authenticity of the data reported due to how much these data sets exchange hands between threat actor groups and how often the data sets are manipulated and merged with new data.
Guidance has been outlined here to support our members with responding to compromised credential data sets appropriately and efficiently. It also aims to provide context as to why some accounts may be reported which are long decommissioned and no longer in use.
Please note: Jisc CSIRT recommends compromised credential notifications are taken seriously and are responded to ASAP to reduce any risk they may pose to your institution.
Where are the credentials sourced from?
Jisc cyber threat intelligence makes use of several sources for compromised credentials. These sources include:
- Trusted, high-confidence intelligence partners
- The NCSC and law enforcement
- Intelligence collected by our cyber threat intelligence analysts
How current are the credentials?
The dark web compromised credential landscape is quite complex. Threat actors capture compromised credentials from many sources, such as:
- Data dumps stolen from organisations have had data breaches
- Infostealer malware logs
- Phishing campaigns
It is commonplace that actors will repost credentials from other actors in their own forums or channels to boost the reputation of these channels or to try and sell other actors work. This makes it extremely difficult to determine the age and legitimacy of credentials as they may be new or simply reposted from older dumps.
Why do some of the credentials not exist?
This is most prominent when it comes to infostealer logs. Users may enter incorrect credentials and the infostealer malware will still capture the credentials entered. Additionally, some credentials may no longer exist in your Active Directory because they are old and have been reposted several times by threat actors, potentially after merging with new data sets.
What service does this effect?
We do not always get the full context regarding which service the compromised credential relates to. If we do have this information, it will be included in the email that we send you. If the affected service is not specified, we recommend that you reset this credential in Active Directory, as well as other high-risk services such as remote access systems.
Investigating reported users
As recommended above, the user accounts detailed within the compromised credentials alert should be verified and further secured if applicable. The steps below are suggested guidelines for this investigation, but you may wish to use your own processes.
The first step should be to check whether the account is still present or active within your infrastructure. See "Identifying disabled or redundant accounts" below to do this within Active Directory. There may be similar processes available for any other high-risk services you host.
If the account, or accounts, are present and active, the following remediation steps should be followed:
Rotate passwords and multi-factor authentication (MFA)
- Disable the user
- Reset user's credentials
- Check if MFA is enabled - if not, consider enforcing this through policy where possible
- Done through Conditional Access Policies if Entra.
- Enforce wherever possible for other MFA services (G Suite, VPN, RAS, etc.)
- Verify that registered MFA is legitimate
- Reregister MFA if there are suspicions that it is not
- Revoke sign in sessions
- Check for suspicious sign ins and, if any are discovered, invoke your compromised account procedure
If you require assistance, our CSIRT team is available to support our members in the case of a compromise.
Mitigation and hardening advice
It is possible to both reduce the risk of credentials being compromised and to reduce the impact where there has been a successful compromise.
The following should be put in place to reduce the likelihood of credentials being compromised:
- Implement MFA on all user accounts (eg staff and students)
- Phishing or Attacker in The Middle resistant MFA, eg FIOD2 tokens, should be used at least for high value targets
- Implement a password policy that includes providing end user guidance on not re-using passwords
- Provide a password manager where feasible
- Disable legacy authentication protocols where possible
- Remove stale accounts
- Further details are in the section below
- As phishing remains one of, if not the most frequently seen, initial access vectors, it is worthwhile to invest in phishing training for users alongside technical defences such as:
- Email filtering and malware scanning
- URL and attachment detonation
- Domain impersonation protection
- DMARC, DKIM and SPF enforcement
The following should be put in place to reduce the impact where credentials have been compromised:
- Ensure good endpoint detection and response (EDR) coverage where possible
- Keep antivirus software up to date
- Deploy identity protection software (eg Defender for Identity)
- Implement good identity management and access control practices
- Notably, use the principle of least privilege
Monitoring and detection solutions should be implemented where possible and tuned so that alerts are generated for high-risk identity events. Some examples of this are:
- Authentication attempts (success/failure)
- MFA challenges and approvals
- Password changes and resets
- Role and permission changes
- Unusual login behaviour
- Impossible travel
- MFA fatigue attacks
- Token misuse
Identifying disabled or redundant accounts
It is good practice to ensure stale accounts are regularly reviewed and subsequently removed where possible. Neglecting to do so needlessly increases potential attack or compromise avenues by providing threat actors, or former employees with malicious intent.
Third party guidance is readily available on the internet and, as above, should be sourced for the specific services in your infrastructure, with a focus on those that are high-risk.
Active Directory
For Active Directory, it is possible to use scripts to identify stale accounts. Sample scripts have been provided below; they may also be developed in-house or sourced online, for example, within the guidance from Microsoft. As always, due diligence should be performed before running scripts on any system.
Example scripts
ADStaleAccounts_User.ps1
# =====================================#
# Stale Active Directory User Accounts #
# =====================================#
Import-Module ActiveDirectory
# ----- SETTINGS -----
$InactiveDays = 90
$ExportPath = "C:\AD_Stale_Accounts"
$DateStamp = Get-Date -Format "yyyyMMdd"
New-Item -ItemType Directory -Path $ExportPath -Force | Out-Null
$InactiveDate = (Get-Date).AddDays(-$InactiveDays)
# ----- GET USERS -----
$Users = Get-ADUser -Filter * -Properties `
DisplayName,
SamAccountName,
CanonicalName,
Enabled,
LastLogonDate,
whenCreated
# ----- FIND STALE ACCOUNTS -----
$StaleUsers = $Users | Where-Object {
$_.Enabled -eq $true -and
(
$_.LastLogonDate -lt $InactiveDate -or
!$_.LastLogonDate
)
}
# ----- EXPORT RESULTS -----
$StaleUsers | Select-Object `
DisplayName,
SamAccountName,
CanonicalName,
LastLogonDate,
whenCreated |
Export-Csv "$ExportPath\Stale_User_Accounts_$DateStamp.csv" -NoTypeInformation
# ----- OUTPUT SUMMARY -----
Write-Host "Stale Account Check Complete" -ForegroundColor Green
Write-Host "Inactive Days Threshold: $InactiveDays"
Write-Host "Total Stale Accounts Found: $($StaleUsers.Count)"
Write-Host "Report Location: $ExportPath"
ADStaleAccounts_Computer.ps1
# =========================================#
# Stale Active Directory Computer Accounts #
# =========================================#
Import-Module ActiveDirectory
# ----- SETTINGS -----
$InactiveDays = 90
$ExportPath = "C:\AD_Stale_Accounts"
$DateStamp = Get-Date -Format "yyyyMMdd"
New-Item -ItemType Directory -Path $ExportPath -Force | Out-Null
$InactiveDate = (Get-Date).AddDays(-$InactiveDays)
# ----- GET COMPUTERS -----
$Users = Get-ADComputer -Filter * -Properties `
SamAccountName,
CanonicalName,
Enabled,
LastLogonDate,
whenCreated
# ----- FIND STALE ACCOUNTS -----
$StaleUsers = $Users | Where-Object {
$_.Enabled -eq $true -and
(
$_.LastLogonDate -lt $InactiveDate -or
!$_.LastLogonDate
)
}
# ----- EXPORT RESULTS -----
$StaleUsers | Select-Object `
SamAccountName,
CanonicalName,
LastLogonDate,
whenCreated |
Export-Csv "$ExportPath\Stale_Computer_Accounts_$DateStamp.csv" -NoTypeInformation
# ----- OUTPUT SUMMARY -----
Write-Host "Stale Account Check Complete" -ForegroundColor Green
Write-Host "Inactive Days Threshold: $InactiveDays"
Write-Host "Total Stale Accounts Found: $($StaleUsers.Count)"
Write-Host "Report Location: $ExportPath"