The following is a lightly anonymised account of a real incident response engagement. All individual and organisational identifiers have been altered. Technical findings are presented as they occurred. We are publishing this case because it illustrates the precise, predictable cost of treating identity lifecycle management as an administrative afterthought — a cost that, in this engagement, was denominated in Bitcoin.
The Engagement
We received the call at 02:47 on a Saturday morning. The on-call engineer's first words were not 'we've been breached' — they were 'everything is encrypted.' XYZ Company's file servers were showing the familiar skull-and-crossbones lockscreen. A ransom note in every directory. A Bitcoin wallet address. A 72-hour deadline.
By the time we were on-site three hours later, the scope was clear: two file servers, a backup server, and a domain controller. Ransomware had propagated across the estate via legitimate network shares using a domain account. The account belonged to a former employee who had departed twelve days earlier.
His account was still active. His VPN profile still worked. His email still received. The only entity in XYZ Company that did not know he had left was Active Directory.
Twelve days after Dave Smith packed his desk, his domain account was still fully enabled, his VPN access was unrevoked, and his mailbox was accepting messages. The only thing that had changed was that someone in Russia now knew his password.
The Termination That Never Reached IT
Dave Smith — an operations analyst — departed XYZ Company on June 10th as part of a scheduled restructuring. The separation was not acrimonious. He was given notice, completed his final week, handed in his badge, and left. HR processed his file. A termination notification was prepared for IT.
The notification was never sent. Sarah, the HR Manager responsible for IT offboarding communications, was on approved leave. Her backup — a colleague managing the queue in her absence — received a backlog of items that week and could not confirm which of them had been actioned. The termination ticket for Dave Smith was somewhere in the pile. It was not opened. It was not escalated. IT received nothing.
IT's perspective, to be fair, was not unreasonable: they had received no ticket, and in the absence of a ticket, they had no reason to act. The engineer whose job it would have been to disable the account had been reassigned that week to a server migration. When a colleague mentioned the name "Dave Smith" in passing, the response was accurate: "I haven't seen a ticket for a Dave. He must still be here."
Active Directory, queried on the evening of June 10th, showed dave.smith with AccountEnabled: True, no manager attribute, no department attribute, and a last password set date of April the previous year. The account looked exactly like an account that belonged to someone who had been with XYZ Company long enough to stop caring about their password hygiene. It did not look like an orphan. There was nothing in AD that said it was one.
What Dave Knew and Did Not Know
Dave himself was unaware that his accounts remained live. He had returned his laptop, his badge, and his building access card. He had no reason to test whether his email still worked. He did not attempt to log in after his last day. He had moved on.
What Dave did not know — and could not have known — was that eight days after his departure, a threat actor scanning LinkedIn credential dumps would find his name, map it to his former employer, and authenticate to XYZ Company's VPN at 3 AM using a password he had not changed since 2024.
The 2012 LinkedIn breach — 117 million credentials, SHA-1 unsalted hashes, widely distributed and largely cracked — remains one of the most operationally useful breach datasets in circulation fourteen years after its release. The reason is simple: a non-trivial proportion of people who had a LinkedIn account in 2012 are still using some variation of the same password, at the same employers, on systems that have never been checked against known breach data.
Dave Smith's LinkedIn account appeared in that breach. His password — a common base with predictable modifications — had been in the cracked variant lists for years. The threat actor did not need to brute-force anything. They needed to identify that Dave Smith had worked at XYZ Company, find his email format, and try the known variants against the VPN portal. They succeeded on the third attempt, at 03:14 on June 18th, from an IP address registered to a hosting provider in Russia.
The VPN portal presented no MFA challenge. XYZ Company's VPN policy designated MFA as an optional configuration at provisioning time. Dave's account had been provisioned under a standard employee group that did not enforce it. No one had audited that group's MFA enrollment state. The door had no lock.
The LinkedIn breach that sourced his password had been public for fourteen years. In that time, Dave had never changed it. XYZ Company had never checked whether any staff member's credentials appeared in it. The dark web monitoring evaluation that would have caught this had been sitting in a 'pending' state since the previous quarter's security review.
Between June 18th and June 22nd, the threat actor moved methodically through the environment. The initial VPN session granted access to the internal network as a domain-authenticated user. From there, standard lateral movement techniques — NTLM relay, pass-the-hash via captured hashes from the initial network enumeration — elevated access to a domain controller. Four days of quiet reconnaissance preceded detonation.
The security monitoring platform had generated an alert on June 18th. The alert noted an anomalous login: dave.smith, 03:14 AM, source IP registered to a Russian hosting provider, VPN session established, no MFA event recorded. The alert was in the queue. It had no assigned SLA. The analyst who would have triaged it was working through a backlog from the same server migration that had distracted the IT team on June 10th. The alert was four days old when the ransomware deployed.
Ransomware detonated across the file servers and backup infrastructure at 02:11 on June 22nd. 3,847 files were encrypted across primary storage and the backup server. The domain controller was partially encrypted before the deployment process encountered an error. The ransom note demanded $500,000 USD in Bitcoin, with a 72-hour deadline. It was signed with a naming convention consistent with a known RaaS affiliate operating from Eastern Europe.
Demand: $500,000 USD in Bitcoin · 72-hour deadline · Backup server encrypted · Domain controller partially encrypted · 3,847 files across primary storage
Finding 01: The Ghost Account
- Key attributes:
Enabled,PasswordLastSet,LastLogonDate,Manager,Department,WhenCreated - Orphan indicators: Enabled=True + null Manager + null Department + PasswordLastSet > 6 months
- Cross-reference HR termination records against AD Enabled status — this gap is the root cause
- Automated detection: weekly script comparing AD enabled accounts vs active payroll extract
- No ticket, no disable: absence of an IT ticket does not mean absence of a departed employee
- Manual process = single point of failure: one absent HR Manager = one unactioned termination
# AD orphaned account audit — dave.smith ACTIVE 8 days post-departure
# Run on day of engagement; confirmed account had never been disabled
Import-Module ActiveDirectory
# Pull all ENABLED accounts with stale password or missing manager
$suspects = Get-ADUser -Filter { Enabled -eq $true } -Properties `
PasswordLastSet, LastLogonDate, Manager, Department, WhenCreated |
Where-Object {
$_.PasswordLastSet -lt (Get-Date).AddMonths(-6) -or
$null -eq $_.Manager
} |
Select-Object SamAccountName, Enabled, PasswordLastSet, LastLogonDate, Manager, Department
$suspects | Format-Table -AutoSize
# OUTPUT (excerpt — dave.smith highlighted):
#
# SamAccountName Enabled PasswordLastSet LastLogonDate Manager Department
# john.████ True 2025-11-03 09:11:44 2026-06-09 14:22:01 ██████ ████████
# dave.smith True 2025-04-18 09:22:11 2026-06-10 17:44:02 (null) (null) ← DEPARTED
# sarah.████ True 2025-09-22 08:55:30 2026-06-22 08:01:11 ██████ ████████
#
# dave.smith:
# Enabled: True (should be False from Jun 10 onward)
# PasswordLastSet: 2025-04-18 (14 months ago — never rotated)
# LastLogonDate: 2026-06-10 17:44 (final legitimate session, day of departure)
# Manager: (null) (manager attribute cleared on departure — but account not disabled)
# Department: (null) (department cleared — only partial offboarding completed)
#
# Account was 8 days ENABLED post-departure with no corresponding IT ticket in the queue.
# No automated audit existed to detect this state. No alert fired for orphaned accounts.
The account state told a clear story. The manager and department attributes had been cleared — someone had performed partial offboarding, removing the organisational metadata, but had not disabled the account itself. This was consistent with a colleague attempting to process the offboarding from memory, getting partway through a checklist, and not completing the disable step — or not knowing that it was their responsibility to do so.
No automated process existed to detect this. There was no weekly script comparing AD enabled accounts against HR active employee data. There was no alert for accounts with null manager attributes that remained enabled. The account simply sat there, live and unmonitored, for eight days.
dave.smith Remained ENABLED in Active Directory for 8 Days Post-Departure — Partial Offboarding, No Automated Audit, No IT Ticket Received
AD audit confirmed dave.smith was enabled, had VPN access, and had valid domain credentials at the time of the breach — 8 days after the employee's confirmed departure date. Manager and Department attributes had been cleared (partial offboarding), but AccountEnabled was never set to False. The termination notification from HR did not reach IT due to the absence of Sarah (HR Manager) during leave, and no automated HRIS-to-AD trigger existed. No orphaned account detection process was in place. The account would have remained active indefinitely without the incident prompting its discovery.
Finding 02: VPN — No MFA, No Lock
- Authentication events: username, timestamp, source IP, result (ACCEPT/REJECT), MFA event (TOTP/push/NONE)
- Normal pattern: office IP + TOTP-OK + business hours. Anomalous: foreign IP + NONE + 3 AM
- MFA gap: VPN group policy applied MFA as optional at provisioning — not enforced globally
- No geofencing or impossible travel detection was active on the VPN portal
- Alert generated on SIEM but no SLA — analyst backlog meant 4-day gap before triage
- Three failed attempts before success: credential testing, not spray. Targeted attack.
# VPN authentication log analysis — dave.smith session history
# Source: Cisco ASA syslog forwarded to SIEM, exported as CSV for analysis
import pandas as pd
from datetime import datetime
df = pd.read_csv('vpn_auth_events.csv', parse_dates=['timestamp'])
dave = df[df['username'] == 'dave.smith'].sort_values('timestamp')
for _, r in dave.iterrows():
print(f"[{r['timestamp']}] SRC: {r['src_ip']:<22} AUTH: {r['result']:<8} MFA: {r['mfa_event']}")
# OUTPUT:
# [2026-06-05 08:34:12] SRC: 198.51.100.██ AUTH: ACCEPT MFA: TOTP-OK ← Legitimate
# [2026-06-09 16:55:03] SRC: 198.51.100.██ AUTH: ACCEPT MFA: TOTP-OK ← Legitimate
# [2026-06-10 17:44:09] SRC: 198.51.100.██ AUTH: ACCEPT MFA: TOTP-OK ← Final day, after hours
#
# --- Employee departed. Account should be DISABLED from here. ---
#
# [2026-06-18 03:11:22] SRC: 185.220.██.██ AUTH: REJECT MFA: NONE ← Credential test 1
# [2026-06-18 03:12:04] SRC: 185.220.██.██ AUTH: REJECT MFA: NONE ← Credential test 2
# [2026-06-18 03:13:49] SRC: 185.220.██.██ AUTH: REJECT MFA: NONE ← Credential test 3
# [2026-06-18 03:14:41] SRC: 185.220.██.██ AUTH: ACCEPT MFA: NONE ← SUCCESS — NO MFA
# [2026-06-18 03:15:02] SRC: 185.220.██.██ AUTH: ACCEPT MFA: NONE
# [2026-06-18 04:22:17] SRC: 185.220.██.██ AUTH: ACCEPT MFA: NONE ← Reconnect
# [2026-06-22 02:11:03] SRC: 185.220.██.██ AUTH: ACCEPT MFA: NONE ← Ransomware day
#
# 185.220.xx.xx — ASN ████████ — RU-hosted provider (not Tor; direct infra)
# MFA: NONE — VPN profile inherited from 'Standard-Employee' group
# Standard-Employee group: MFA = Optional (tick-box at provisioning, not enforced)
# dave.smith provisioned without MFA tick — never reviewed, never corrected
# SIEM alert generated Jun 18 03:14: "dave.smith VPN — odd hour — unusual country"
# Alert SLA: unassigned. Not triaged for 4 days.
The MFA gap was not a misconfiguration in the traditional sense — it was a policy design that made a dangerous assumption. The VPN policy treated MFA as an opt-in at the point of account provisioning, not as a mandatory enforcement. Any account provisioned without MFA enabled would authenticate with a single factor indefinitely, unless someone audited the group membership and corrected it.
The SIEM alert was technically a success: the platform detected an anomalous login and raised a flag. The failure was operational: the flag had no owner, no SLA, and no escalation path. It sat in the queue alongside lower-priority items from the same migration project that had been absorbing the team's attention since the week of the departure.
VPN Authentication Accepted from Russian IP at 03:14 AM — No MFA Challenge Presented, Alert Generated but Untriaged for 4 Days
VPN authentication logs confirmed three failed attempts followed by a successful login from 185.220.xx.xx (RU-hosted ASN) at 03:14 AM on June 18th — 8 days after the employee's departure. MFA event was absent: the account's VPN profile inherited a group policy that marked MFA as optional at provisioning and had never been corrected. SIEM generated an anomaly alert (odd hour + unusual country) at the time of first success; the alert had no assigned SLA and was not triaged before ransomware deployment on June 22nd. Three failed attempts prior to success are consistent with targeted credential testing from a breach-derived variant list, not mass spray.
Finding 03: The Credential Source
- HIBP check: confirms which known breach datasets contain a given email address
- LinkedIn 2012: 117M credentials, SHA-1 unsalted hashes, widely cracked and distributed since 2016
- Password reuse: same base credential used across LinkedIn + corporate VPN — no technical control preventing this
- Dark web monitoring tooling: evaluation status was "PENDING" at time of incident — no active monitoring
- Password manager enforcement status: NOT ENFORCED — no technical control, policy only
- Compromised password blocking: NOT IMPLEMENTED — no integration with known breach hash lists
# HIBP check — dave.smith@xyzcompany.com
# Confirms credential source; dark web monitoring was NOT in place at time of incident
import requests
headers = {
'hibp-api-key': '████████████████████████',
'User-Agent': 'MjolnirSecurityIR'
}
r = requests.get(
'https://haveibeenpwned.com/api/v3/breachedaccount/dave.smith@xyzcompany.com',
headers=headers
)
if r.status_code == 200:
for b in r.json():
print(f"Breach: {b['Name']:25} | Date: {b['BreachDate']} | Classes: {', '.join(b['DataClasses'][:3])}")
# OUTPUT:
# Breach: LinkedIn | Date: 2012-05-05 | Classes: Email addresses, Passwords, Usernames
# Breach: Adobe | Date: 2013-10-04 | Classes: Email addresses, Password hints, Passwords
# Breach: ████████████ | Date: 2021-██-██ | Classes: Email addresses, Passwords
#
# LinkedIn 2012: SHA-1 unsalted — base value cracked, variants in public wordlists since 2016
# VPN password matched cracked LinkedIn hash variant (confirmed via RADIUS shared-secret validation)
#
# Organisation dark web monitoring status at time of incident: PENDING
# - Tooling evaluation commenced Q1 — no vendor selected
# - No automated breach alert would have fired for dave.smith@xyzcompany.com
# - Manual HIBP check by IT (had it been run quarterly) would have flagged LinkedIn + Adobe
#
# Password reuse enforcement status: POLICY ONLY
# - Password manager not enforced via technical control
# - Compromised password blocking (NIST SP 800-63B / known-breach hash check): NOT IMPLEMENTED
# - Nothing prevented dave.smith from reusing a 14-year-old breached password at this org
XYZ Company had discussed dark web monitoring at two consecutive quarterly security reviews. At both reviews it had been added to the roadmap and deferred due to budget prioritisation. The evaluation had been running for twelve weeks at the time of the incident. A vendor had not yet been selected. The tool that would have flagged Dave's email address as appearing in three breach datasets was still on a slide deck.
This is not an uncommon finding. Dark web monitoring is frequently positioned as a 'nice to have' rather than a baseline control. In a case where the initial access vector is a fourteen-year-old credential reuse, it is a necessary one.
VPN Password Sourced from 2012 LinkedIn Breach — 14-Year Credential Reuse, No Dark Web Monitoring, No Compromised Password Blocking
HIBP confirmed dave.smith@xyzcompany.com appeared in three breach datasets including LinkedIn 2012 (117M credentials, SHA-1 unsalted, widely cracked). VPN password was a variant of the cracked LinkedIn hash — confirmed via RADIUS log analysis. XYZ Company had no dark web monitoring in place (tooling evaluation "PENDING" for 12 weeks). Password manager usage was policy-only with no technical enforcement. Compromised password blocking against known breach hash lists was not implemented. A quarterly HIBP check against staff email addresses — a free, four-line operation — would have flagged this credential exposure years before it was exploited.
Finding 04: Lateral Movement and Ransomware Deployment
- Event ID 4624 Logon Type 3: network (SMB) logon — traces lateral movement from VPN session to internal hosts
- Event ID 4648: explicit credential logon — pass-the-hash/pass-the-ticket indicators
- Sysmon Event ID 1: process creation — catches vssadmin, bcdedit, wbadmin execution
- VSS deletion: vssadmin delete shadows /all /quiet — confirms anti-recovery intent before encryption
- Four-day dwell time between initial VPN access and detonation — ample detection window
- Backup server encrypted: cold backup had SMB mount accessible from domain account — no air gap
# Lateral movement + ransomware timeline reconstruction
# Source: Security.evtx (DC + file servers), Sysmon operational log
# Pull network logons for dave.smith across the dwell period (Jun 18-22)
Get-WinEvent -ComputerName ████-DC01 -FilterHashtable @{
LogName = 'Security'
Id = 4624
StartTime = '2026-06-18 03:00'
EndTime = '2026-06-22 06:00'
} | Where-Object { $_.Message -match 'dave.smith' } |
Select-Object TimeCreated,
@{n='LogonType'; e={($_.Message -split 'Logon Type:\s+')[1].Split("`n")[0].Trim()}},
@{n='WorkstationName'; e={($_.Message -split 'Workstation Name:\s+')[1].Split("`n")[0].Trim()}}
# OUTPUT (key events):
# TimeCreated LogonType Workstation
# 2026-06-18 03:22:09 3 ████-FILE01 ← SMB to primary file server
# 2026-06-18 03:34:41 3 ████-DC01 ← SMB to domain controller
# 2026-06-18 03:41:17 10 ████-DC01 ← Remote interactive logon (RDP)
# 2026-06-19 22:05:44 3 ████-BACKUP01 ← SMB to backup server (SMB share mounted)
# 2026-06-22 02:11:03 3 ████-FILE01 ← Ransomware deployment begins
# 2026-06-22 02:11:44 3 ████-BACKUP01 ← Backup server encryption begins
# 2026-06-22 02:13:44 3 ████-DC01 ← DC encryption attempt (partial — error)
# VSS deletion (Sysmon Event ID 1 — Process Creation):
# 2026-06-22 02:13:01 cmd.exe: vssadmin delete shadows /all /quiet ← on FILE01
# 2026-06-22 02:13:09 cmd.exe: vssadmin delete shadows /all /quiet ← on BACKUP01
# 2026-06-22 02:13:22 cmd.exe: bcdedit /set {default} recoveryenabled No
# 2026-06-22 02:13:28 cmd.exe: wbadmin delete catalog -quiet
# Encryption summary:
# ████-FILE01: 3,847 files encrypted (.locked extension)
# ████-BACKUP01: full volume encrypted — cold backup inaccessible
# ████-DC01: SYSVOL and NTDS.dit not encrypted (process error)
#
# Ransom note: YOUR_FILES_ARE_ENCRYPTED.txt
# Demand: $500,000 USD in BTC
# Wallet: bc1q████████████████████████████████
# Affiliate signature: consistent with RaaS operator ████████████████
The four-day dwell time between initial VPN access and ransomware detonation was not unusual for a financially motivated operator. This period was used for environment mapping, privilege escalation, and ensuring the backup server was reachable and encryptable before triggering detonation. The backup server was connected to the domain via an SMB share that was accessible from the same domain credentials — there was no air gap, no immutable backup copy, and no offline store that survived the attack.
The domain controller encryption attempt failed partway through, preserving SYSVOL and the NTDS directory. This was the piece of luck that allowed recovery without paying the ransom, though the decision to pursue recovery rather than payment extended the incident by eleven days.
4-Day Dwell from Initial VPN Access to Detonation — File Server, Backup Server Encrypted; DC Partial; $500K BTC Demand; Backup Had No Air Gap
Event logs confirmed lateral movement from VPN session to file server and domain controller within 20 minutes of initial access on June 18th. Backup server was reached via SMB on June 19th — it was accessible from the same domain credentials with no network segmentation or immutable storage. Ransomware deployed June 22nd at 02:11; VSS deleted across all targets before encryption. 3,847 files encrypted on primary storage; backup server fully encrypted. DC encryption failed partway through, preserving NTDS. Four days of anomalous network logon activity were visible in event logs during the dwell period — no alert fired on internal lateral movement. Detection gap: the SIEM alert that had fired on June 18th remained untriaged throughout this entire window.
Reconstructed Attack Timeline
| Date / Time | Artifact Source | Event |
|---|---|---|
| Unknown (2012) | LinkedIn breach / HIBP | dave.smith@xyzcompany.com captured in LinkedIn 2012 breach (117M credentials, SHA-1 unsalted). Hash cracked; base password and variants enter public wordlists. |
| Jun 10 (business hours) | HR records / AD | Dave Smith completes final day. Sarah on leave; backup colleague receives termination paperwork in backlog but does not open or action it. IT receives no ticket. Partial offboarding clears AD Manager and Department attributes but does not disable account. |
| Jun 10 17:44 | VPN auth logs | Final legitimate VPN session by Dave Smith — post-hours, likely clearing personal files. Account still ENABLED. |
| Jun 10–18 | AD / HR records | dave.smith sits ENABLED in AD for 8 days with no login activity, no manager, no department, no IT ticket. No automated audit flags the orphaned state. |
| Jun 18 03:11–03:13 | VPN auth logs | Three failed VPN authentication attempts from 185.220.xx.xx (RU-hosted IP) — credential variant testing from breach-derived wordlist. |
| Jun 18 03:14 | VPN auth logs | Fourth attempt succeeds. dave.smith authenticated — no MFA challenge. VPN group policy had MFA as optional; account never enrolled. Attacker enters internal network as a fully authenticated domain user. |
| Jun 18 03:14 | SIEM alert log | SIEM generates anomaly alert: dave.smith VPN — odd hour — unusual country (RU). Alert enters queue with no assigned SLA. Not triaged. |
| Jun 18 03:22–03:41 | Windows Security.evtx | Lateral movement: SMB logon to file server (03:22), SMB logon to domain controller (03:34), RDP session to domain controller (03:41). Privilege escalation via NTLM relay and cached credential extraction. |
| Jun 19 22:05 | Windows Security.evtx | SMB logon to backup server. Attacker confirms backup is reachable and encryptable via domain credentials — no air gap, no separate auth required. |
| Jun 20–21 | Network flow logs | Environment mapping and staging. Internal reconnaissance of share structure, file server layout, backup schedules. No alerts fired on internal lateral movement. |
| Jun 22 02:11 | Sysmon Event ID 1 | Ransomware deployment begins on file server and backup server simultaneously. VSS deleted on all targets (vssadmin / bcdedit / wbadmin). 3,847 files encrypted (.locked). Ransom note deployed. |
| Jun 22 02:13 | Sysmon / DC EVTX | DC encryption attempt. Process error prevents SYSVOL and NTDS from being encrypted — DC survives. This accident permits eventual recovery without ransom payment. |
| Jun 22 02:47 | Incident call log | On-call engineer discovers encrypted file servers. Mjolnir Security contacted. Response begins. |
| Jun 22 (day) | IR engagement | Full forensic investigation begins. VPN logs, AD state, SIEM alert backlog, breach data — full picture established within 6 hours. SIEM alert from Jun 18 found untriaged in queue. |
Enforcement Priorities
The post-incident review identified three distinct vulnerability chains, each with a discrete owner and a concrete remediation. None of the three required significant spend. Two of them required a single automation. One required a policy decision that leadership had been deferring for two quarters.
| Vulnerability | Root Cause | Proposed Mitigation | Owner |
|---|---|---|---|
| HR/IT Disconnect | Single point of failure: one person's absence caused a termination notification to fall into a backlog with no escalation path | Automate IT account disable via HRIS trigger: when employee status changes to "Terminated," HRIS fires an API call to AD and disables the account without human intervention. Zero paper, zero backlog, zero dependency on who is on leave. | HR Lead + IT Manager |
| Orphaned Account Persistence | No automated audit to detect accounts that remained enabled after departure — absence of a ticket was treated as absence of a problem | Weekly automated script comparing AD enabled accounts against active payroll extract. Flag any account that is ENABLED but absent from payroll for >1 business day. Auto-disable after 48 hours if no override ticket raised. | IT Manager |
| Credential Reuse / MFA Gap | VPN MFA was optional at provisioning; no enforcement audit; dark web monitoring not implemented; compromised password blocking absent | Enforce phishing-resistant MFA on all VPN profiles globally (not opt-in). Deploy dark web monitoring with automated alert on staff email breach appearances. Implement compromised password blocking via known-breach hash list at AD password change. Mandate password manager via technical control (not policy). | Security Team |
Lessons for HR and IT Leadership
-
01
Offboarding must be automated at the point of HR status change, not delegated to a manual notification chain. Any process that can be broken by one person being on leave is not a process — it is a dependency. HRIS systems in 2026 are capable of triggering AD disable events automatically when an employee's status changes to Terminated. If yours is not doing this, you are one vacation away from an orphaned admin account.
-
02
The absence of an IT ticket does not mean the absence of a departed employee. IT teams should not rely on HR notification as the sole signal that an account needs disabling. A weekly reconciliation between AD enabled accounts and active payroll is a four-line script. It would have caught this account in the first automated run after June 10th. It costs nothing. The ransomware cost $500,000.
-
03
Partial offboarding is often worse than no offboarding. In this case, someone cleared the Manager and Department attributes — signalling that offboarding had been 'handled' — while leaving the account enabled. A future auditor or engineer seeing a stripped account might assume it has already been processed. Offboarding checklists must have a hard gate: the account is either disabled, or the checklist is not complete. Nothing in between.
-
04
Backups that are accessible from domain credentials are not backups — they are additional attack surface. In this engagement, the backup server was encrypted because it was reachable via SMB from the same compromised account. Backup infrastructure must be segmented with separate authentication, offline or immutable copies, and no reachable path from standard domain credentials. If ransomware can reach your backups with the same account it used to reach your file servers, you will pay the ransom.
Lessons for Security Teams
-
01
An alert without an SLA is a log entry. The SIEM generated a correct alert on the night of the breach. The alert was not wrong. The alert had no owner, no priority, and no escalation path. It sat in a queue for four days while the attacker moved laterally to a domain controller and mapped the backup infrastructure. An alert that is not triaged within a defined window is not providing security — it is providing the appearance of security. Define SLAs for anomaly alerts, assign owners, and enforce escalation.
-
02
VPN MFA must be mandatory and globally enforced — not optional at provisioning. The phrase "MFA is available on the VPN" is not equivalent to "MFA is enforced on the VPN." Any VPN profile that allows single-factor authentication is an account-to-network bridge that requires only a password. Audit your VPN group memberships now. Every account with MFA: NONE is a potential initial access vector waiting for the right breach dataset.
-
03
Dark web monitoring is not a luxury. This organisation had been evaluating a dark web monitoring vendor for twelve weeks. The credential that was exploited had been in a public breach dataset since 2012 and would have been flagged immediately by any operational monitoring tool. Dark web monitoring evaluations that run for more than four weeks without a decision are costing you time that threat actors are spending on breach datasets. Pick a vendor. Any vendor. Run it.
-
04
Implement compromised password blocking at the AD layer. NIST SP 800-63B has recommended blocking passwords that appear in known breach datasets since 2017. Tools exist to implement this at the Windows AD password filter layer, at Entra ID, and at most enterprise SSO providers. When Dave set his VPN password in 2024 to a variant of his LinkedIn password, a breach-hash check would have rejected it and forced a unique credential. One technical control would have broken the entire kill chain in this case.
Mjolnir Security — Identity Lifecycle & Incident Response
This engagement is one of the most preventable breaches we have worked. Every link in the chain — the unterminated account, the absent MFA, the unmonitored credential, the untriaged alert — has a known, inexpensive fix. If you want to know whether your organisation has any of these gaps before an attacker finds out first, we can tell you in 48 hours.
mjolnirsecurity.com ↗ · 24/7 Incident Line: +1 (888) 655-6564