Investigating Active Directory Account Lockouts Like an Analyst

Yeah so account lockouts. Most of them are boring. Phone still has the old password, Outlook on a laptop that never got the new one, some backup job nobody owns running as a real user account. You clear the cache, unlock the user, move on with your life.

The interesting ones are when something that talks to AD is hanging out where strangers can reach it — VPN portal, random web app on 443 that does NTLM/LDAP, RDP open to the world — and now random IPs on the internet get a vote on your lockout policy. Those are the tickets that actually suck to figure out, and also the ones worth writing down.

This is how I usually chase them. Not a vendor playbook. Just what tends to work when you’ve got Security logs, a DC, and not a lot of patience.

What even is a “lockout” here

Domain lockout = enough failed auths hit whatever threshold is in Group Policy, and AD locks the account. You’re mostly living in:

  • 4625 — logon failure (shows up on the machine that saw the attempt; also on DCs depending on path)
  • 4771 — Kerberos pre-auth failure (DC; super useful when it’s Kerberos-y)
  • 4740 — account got locked (DC; look at Caller Computer Name when it’s actually populated)

If those audit categories aren’t on, you will not see the story. Full stop. I’ve watched people invent conspiracy theories for an hour and it was just “we never enabled the audit policy.” Fix GPO first. Account lockout auditing, logon failures, Kerberos auth service failures, user account management success for 4740. Microsoft’s docs are fine for the checkboxes.

Also: local SAM lockout ≠ domain lockout. Confirm which one you actually hit before you spiral.

Boring causes — check these first so you don’t look dumb

  1. User changed password, phone/mail profile still has the old one
  2. Laptop that was asleep for three days, mapped drive with saved creds
  3. Scheduled task / backup / service still running as that user
  4. Someone fat-fingered the password on a shared workstation five times

If 4740 points at a known internal host and the user just rotated a password… yeah. Tell them to sign out of everything, clear saved passwords, unlock, done. Don’t spend forty minutes on threat intel for that.

Less boring causes

  • Public stuff bound to AD — SSL VPN, OWA-style junk, “custom intranet” on 443 that binds to LDAP/NTLM, RD Gateway, etc.
  • RDP exposed — external spray tools, or internal scripts that look like RDP clients doing dumb things
  • Scanners — credentialed vuln scans with brute modules and default username lists (anonymous and friends). Yes, you can lock people out with your own scanner. Ask me how I know that pattern shows up.
  • Weird edge cases — home router / rebinding nonsense is rare but I’ve seen enough cursed remote-worker setups that I don’t laugh it off immediately

Read the event like it’s lying to you (because sometimes it is)

When 4625 is useful, don’t just glance at “bad password” and close the ticket:

  • Logon Type — 3 network, 10 remote interactive, 2 interactive… type 3 from the internet is a different mood than type 2 at a desk
  • Status / Sub Status0xc000006a bad password, 0xc0000064 user doesn’t exist (spray smell), etc.
  • Auth package — NTLM vs Kerberos changes where you look next
  • Workstation Name — often blank through NAT/portals. When it’s something like mstsc.exe, pay attention
  • Source Network Address — helpful until a proxy lies to you

Sanitized shape of the kind of 4625 that makes me sit up:

EventID: 4625
Logon Type: 3
Account Name: bwilkinson
Account Domain: CONTOSO
Failure Reason: Unknown user name or bad password
Status: 0xc000006d
Sub Status: 0xc000006a
Workstation Name: mstsc.exe
Source Network Address: 203.0.113.50
Authentication Package: NTLM
Logon Process: NtLmSsp

And the lockout:

EventID: 4740
Account That Was Locked Out: flastname
Caller Computer Name: mstsc.exe
Subject: DC01$

Workstation Name: mstsc.exe is a recurring weirdo. It’s not proof of nation-state anything. It is a fingerprint that shows up a lot with RDP-client-shaped traffic, scripts, spray tooling, etc. Pair it with “is 3389 or RDG actually reachable?” and whether source IPs look external. Don’t page the CEO over one field alone — but don’t shrug it off either.

What I actually do, in order

  1. Get 4740 for the user on the DCs — time, which DC, caller computer if present
  2. Get 4625 / 4771 in the same window (±15 min). Burst vs slow drip matters
  3. Count distinct sources — one internal host after a password change, or twenty external IPs?
  4. Look at the attack surface — anything AD-backed on 80/443/3389 public? Open the IP from an isolated lab browser, not your admin session with cookies loaded. For RDP, test from a lab, not from prod jumpboxes if you can help it
  5. If caller/source is empty or is basically “the DC” — stop expecting the DC to name the attacker. Auth terminated on a VPN/portal/RDS broker. Go get those logs

PowerShell when I have rights on a DC (prefer constrained / proper admin path, don’t be dumb with domain admin everywhere):

# Lockouts last 24h for a user
Get-WinEvent -ComputerName DC01 -FilterHashtable @{
  LogName   = 'Security'
  Id        = 4740
  StartTime = (Get-Date).AddHours(-24)
} | Where-Object { $_.Message -match 'jsmith' } |
  Format-List TimeCreated, Message

# Failures
Get-WinEvent -ComputerName DC01 -FilterHashtable @{
  LogName   = 'Security'
  Id        = 4625,4771
  StartTime = (Get-Date).AddHours(-24)
} | Where-Object { $_.Message -match 'jsmith' } |
  Select-Object -First 50 TimeCreated, Id, Message

If you’ve got a centralized log search, same idea — filter those codes + username + time. I’m not religious about the tool. I’m religious about not guessing.

When the DC won’t tell you the real client

This is the part people hate. External auth hits a reverse proxy / VPN concentrator / RDS gateway. DC sees a service host or nothing useful. Caller Computer Name is blank or useless. That’s normal, not a broken SIEM.

At that point I’m not “digging harder into 4740.” I’m asking: where did the password get typed? Get portal logs, broker logs, firewall NAT logs. No edge logs = weak attribution. Don’t promise magic.

Netlogon debug can help for some secure-channel / trust weirdness. It’s noisy. Temporary only:

nltest /dbflag:0x2080ffff
net stop netlogon
net start netlogon
# reproduce the issue
nltest /dbflag:0x0
# then read:
# %SYSTEMROOT%debugnetlogon.log

Turn it off. Leaving verbose Netlogon logging on a busy DC is how you get a full disk and a sad AD team.

NTLM-heavy shops: look at the stronger NTLM operational auditing Microsoft talks about for advanced auditing / Defender for Identity style setups (8004-type secure channel naming when it’s actually configured). Sometimes that names the machine making the bad auth when 4625 is being coy.

Names that make me raise an eyebrow

  • mstsc / mstsc.exe — RDP client smell
  • RDESKTOP — often public RDP-ish stuff
  • ubuntu — domain-joined Linux service or something public and weird
  • anonymous — scanner default lists
  • Usernames that look more like rockyou than your HR export

None of those are automatic “breach.” They’re leads.

Quick triage so you’re not reinventing it every time

What you see My guess What I do next
One user, one internal host, right after password change Stale creds Clear cached logons / app passwords, unlock
One user, many external IPs, type 3 NTLM Spray / public portal Find the AD-backed edge, block, MFA, stop the bleeding
Many users, same external IP Password spray Edge block + IdP/VPN review + watch for successes
Caller mstsc.exe, 3389 open RDP exposure Close public RDP; hunt successful 4624 type 10/3
Service account on a schedule Task/backup/job Fix the job account; gMSA if you can

Stuff that actually reduces lockout tickets

  • Stop putting AD auth on the open internet without MFA / sensible controls
  • Kill public RDP. VPN + conditional access or equivalent, not “RDP forever”
  • Service accounts that aren’t also Bob from accounting
  • After password changes, a dumb checklist: phone, laptop, mapped drives, VPN profile
  • If you run scanners with brute force modules, know their username lists so you don’t page yourself

Anyway

Lockouts are a symptom. The question I care about is: which auth path took a wrong password enough times, and can a stranger hit it? If you can answer that with events and edge logs, you’re doing the job. If you’re only staring at a red badge in a dashboard with no 4625/4740 story, you’re guessing.

Next time I’ll dig more into the kerberoast / AS-REP side of “bad auth that isn’t a lockout” — different events, same energy.

Leave a Reply

Your email address will not be published. Required fields are marked *