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
| Event ID | 4625 | An account failed to log on. |
|---|---|---|
| Recorded on | fs-01.lab.example | The machine that processed the logon, not the one the person sat at. |
| Account | LAB\student01 | Who the request claimed to be. |
| Logon type | 3 | Network logon, such as opening a file share. Type 2 would be at the keyboard, type 10 over Remote Desktop. |
| Status / Sub status | 0xC000006D / 0xC000006A | A bad password for an account that exists. A missing account shows 0xC0000064 instead. |
| Workstation name | WS-02 | Where the request came from, as the client reported it. |
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.
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
- Microsoft, Active Directory Domain Services overview
- Microsoft, Monitoring Active Directory for signs of compromise
Skills used
- Reading event 4625 field by field
- Linking an event to account and source
- Knowing what an alert leaves out
Tools in this entry
Active Directory Domain Services I use it
Official documentation for Active Directory Domain ServicesGroup Policy I use it
Official documentation for Group PolicyWindows security auditing I use it
Official documentation for Windows security auditing