The Active Directory lab · Part 2 of 3

Tracing a failed domain sign-in

Once I had Windows machines to look after, Active Directory became one of the tools I used most. This is how I read the evidence a single logon leaves behind, and which questions it can and cannot answer.

I started the lab to host a Minecraft server for my friends. Once I had Windows machines to look after, Active Directory became one of the tools I used most. It gave me a place to manage identities and put the activity I saw on Windows endpoints in context.

The questions got more interesting from there. Which account made that request? Which machine recorded it? Was the access consistent with what I intended? This entry is about how a single logon answers those questions, and where it stops answering them.

Three pieces that are easy to blur together

It helped me to keep three things separate, because “Active Directory” gets used as a name for all of them.

  • AD DS (Active Directory Domain Services) is the directory itself. It holds the user accounts, the computer accounts, and the groups they belong to. When a machine joins the domain, it gets an identity there too.
  • Group Policy is how settings reach those machines. One of the settings it can push is the audit policy, which decides what Windows writes to its Security log in the first place.
  • The Windows hosts produce the evidence. A workstation, a member server and a domain controller each record different events, because each plays a different part in the same sign-in.

That last point matters most when I go looking: the event I want is not always on the machine in front of me.

What a failed logon looks like

Here is a failed network logon written out the way the Security log presents it. The names are examples I made up for this entry, not records from my lab.

Illustrative event · sample names, not from my lab

Fields of an illustrative Windows event 4625
Event ID4625An account failed to log on.
Recorded onfs-01.lab.exampleThe machine that processed the logon, not the one the person sat at.
AccountLAB\student01Who the request claimed to be.
Logon type3Network logon, such as opening a file share. Type 2 would be at the keyboard, type 10 over Remote Desktop.
Status / Sub status0xC000006D / 0xC000006AA bad password for an account that exists. A missing account shows 0xC0000064 instead.
Workstation nameWS-02Where the request came from, as the client reported it.
Read the sub status before the count. Six failures with 0xC000006A mean a real account and a wrong password, which points at a person or a saved credential. Six with 0xC0000064 point at someone guessing names.

The same attempt also leaves a trace on the domain controller, because the file server asked it to check the password. Depending on whether Kerberos or NTLM was used, that shows up as a different event there. If I only look at the file server, I see the failure. If I only look at the domain controller, I see the check. I need both to tell the whole story.

PowerShellFile server · admin shellExample output · substituted names and addresses

When the SIEM showed a burst of failures, I went to the machine that recorded them and pulled the fields I actually reason with.

Get-WinEvent -FilterHashtable @{ LogName = 'Security'; Id = 4625; StartTime = (Get-Date).AddHours(-1) } |
ForEach-Object { $x = [xml]$_.ToXml(); [pscustomobject]@{
  Time = $_.TimeCreated; Account = ($x.Event.EventData.Data | ? Name -eq 'TargetUserName').'#text'
  SubStatus = ($x.Event.EventData.Data | ? Name -eq 'SubStatus').'#text'
  Workstation = ($x.Event.EventData.Data | ? Name -eq 'WorkstationName').'#text' } }
Show output
Time                 Account    SubStatus   Workstation
----                 -------    ---------   -----------
07/11/2026 08:20:00  student01  0xc000006a  WS-02
07/11/2026 08:19:00  student01  0xc000006a  WS-02
...

Example output. Reading the event’s XML is what gets at named fields like SubStatus instead of the long message text.

Which machine recorded it

The easiest mistake is looking on the wrong host. A sign-in is a conversation between the client, the service it wants and the domain controller, and each one writes down its own part:

  • The client knows what the user did, but not whether the server accepted it.
  • The server knows who tried to connect to it and whether it let them in.
  • The domain controller knows whether the credentials were valid.

That is also why the audit policy matters so much. If Group Policy never told a machine to audit logons, the event simply does not exist, and its absence says nothing about whether the logon happened.

Was it the access I intended?

An event answers “what happened”. It does not answer “was that okay”. For that I have to compare it with what I meant to allow: which groups should reach that share, whether a lab account should ever sign in to an admin host, whether a daily account and an administrative account are being kept apart.

For the example event above, the comparison is short. student01 is a lab user who is meant to reach the share on FS-01, so the access is intended; the wrong password is not. That turns the question from “is this an attack?” into “what on WS-02 is still using an old password?”, which is something I can actually check. The attack-lab exercises run the same comparison for a group change and an admin sign-in, and SOC-0142 runs it on a simulated cluster with a firewall record beside it.

Takeaway: read a logon in three passes: which machine recorded it, what the sub status says, and whether the account was meant to have that access. The third pass is the one that turns an event into a finding.

Further reading

Skills used

  • Reading event 4625 field by field
  • Linking an event to account and source
  • Knowing what an alert leaves out

All skills, grouped by what job postings ask for

Tools in this entry

Every tool and its documentation