Windows Security Audit Policy and Event Log Investigation in Practice — Becoming an IT Team That Can Read Event 4625
· Updated: · Go Komura · Windows, Security, Event Log, Audit Policy, Log Design, PowerShell, Information Systems
Revision history (first version, published Aug 1, 2026)
- First published
Cite this article(DOI (registered archive): 10.5281/zenodo.22170837)
The DOIs below refer to previously archived versions and may not match the current text. Use this page’s URL to reference the current text.
Go Komura (2026). Windows Security Audit Policy and Event Log Investigation in Practice — Becoming an IT Team That Can Read Event 4625. KomuraSoft LLC. https://comcomponent.com/en/blog/windows-security-audit-policy-guide/
- DOI (registered archive)
- 10.5281/zenodo.22170837
- DOI (last registered version)
- 10.5281/zenodo.22170838
“An account has been locking out over and over since last night. Find out why.” “Check whether someone is trying to sign in with a former employee’s account.” “Can you tell when and who ran what on this server?” — these are the requests that land out of nowhere on the IT staff of a small or midsize company, or on a developer who delivers systems to a customer site. And the thing you end up leaning on is the Windows Security event log.
Open Event Viewer, though, and two realities are waiting for you. Either the event you want was never recorded (the audit policy was not enabled) or it is buried under a flood of events and unreadable (the log is full of noise and has grown huge). Security auditing is something you “get if you turn it on,” but unless you design what to record and how far, it will not help you when it matters.
flowchart TB
accTitle: The two realities waiting in Event Viewer
accDescr: Open Event Viewer and there are two realities, either the audit policy was not enabled so the event you want was never recorded, or the log is full of noise and has grown huge so the event is buried under a flood of entries, which means you need to design what to record and how far
open["Open Event Viewer"] --> real{"Which reality is waiting?"}
real -->|Not recorded| none["The event you want was never recorded"]
real -->|Buried| noise["Unreadable under a flood of events"]
none -.-> cause1["Audit policy disabled"]
noise -.-> cause2["Full of noise and grown huge"]
none --> design["Design what to record and how far"]
noise --> design
Figure 1: Either “not recorded” or “buried and unreadable.” Both come from never having designed the scope of what to record.
This article separates two things: the settings that keep the logs an investigation needs, and the procedure for finding the cause in the logs you have. It covers how audit policy works (the two systems, basic and advanced), the subcategories a small-to-midsize environment should enable at minimum, how to read 4624/4625/4740/4688, Security log capacity design, and how to investigate with PowerShell. The technical explanations are based on primary sources as of August 2026.
If the articles this site has covered so far — NTLM auditing, SMB signing, BitLocker, and the firewall — are about hardening the defenses, this article is about making it possible to confirm afterwards what happened, and it is the sequel that ties them together.
1. The Bottom Line First
To make your logs usable for investigation, line up three things: record what you need, read the right item on the right machine, and preserve it before it disappears. The important part is not stopping at enabling auditing.
If you are about to configure auditing: standardize on the advanced side and record only what you need
- Audit policy comes in two systems, “basic” and “advanced” (Advanced Audit Policy), and you must not mix them. Microsoft states explicitly that using both leaves audit results in an unexpected state. Standardize on the advanced side (more than 40 subcategories).1
- To check the current state, run
auditpol /get /category:*. It lists the audit settings that are in effect right now, regardless of whether they come from GPO or from local settings.2 - Do not “enable everything.” Enabling subcategories that generate huge numbers of events buries the events that matter in noise and affects performance too. Start from Microsoft’s baseline recommendations and add only what you need.34
If you are investigating right now: check the recording machine and the fields, not just the event ID
- A successful sign-in is 4624 and a failure is 4625. For 4624 you tell “what kind of sign-in” it was from the logon type (2 = interactive, 3 = network, 10 = Remote Desktop, and so on).5
- For 4625, the Status/Sub Status codes tell you the reason for the failure. The standard set is 0xC0000064 = user name does not exist, 0xC000006A = wrong password, 0xC0000072 = account disabled, 0xC0000234 = account locked out.6
- Which machine an event is recorded on is fixed. 4624/4625 go to the machine that was accessed, credential validation (4776) goes to the machine that has authority over the credential (a domain controller for a domain account), and Kerberos pre-authentication failure (4771) goes to a domain controller. Look at the wrong machine and you will misdiagnose it as “there is no log.”678
Needed in both cases: design log retention and the handling of sensitive information
- For the Security log, the design of the container (maximum size and retention) is half the job. If retention is set to overwrite, the oldest events disappear one by one. Check the maximum size and record count with
Get-WinEvent -ListLog Security, and expand it by working backwards from the number of days you need to retain.910 - Command-line logging for process creation (4688) is powerful, but the trade is the risk of secrets landing in the log in plain text. Review your scripts before enabling it.1112
Choose where to read based on your goal or symptom
| What you want to know now | What to get straight first | Where to read |
|---|---|---|
| I want to tidy up the audit settings | Check the settings actually in effect and the log capacity, then choose the subcategories you need | Section 2: checking the settings, Section 5: capacity and retention, Section 3: the decision table |
| I want to read sign-in successes and failures | For success look at the logon type, for failure look at Status/Sub Status | 4.1: 4624, 4.2: 4625 |
| I want to know why an account keeps locking out | Find the origin with 4740, and check the destination and the DC as well for the record of the failures | 4.3: 4740 |
| I want to find out who ran what | Read the parent process in 4688 and the task definition in 4698. Adding command-line logging requires a review first | 4.5: 4688, 4.6: 4698, Section 7: pitfalls |
| The log I want is missing, or disappears quickly | Check where it is recorded, the audit settings, and the span actually retained | Section 2, Section 5, Section 7 |
| I want to investigate the logs in bulk | Preserve them as evtx first, then extract by ID and time range | 6.3: preservation, 6.2: PowerShell |
If you have already been handed an investigation request, preserve the log using the method in 6.3, check the notes on recording machines and clock synchronization in Section 7, and then read the relevant event in Section 4. If you are tidying up the settings, check the current state in Sections 2 and 5, then move on to Section 3.
In the diagram a solid line marks a relation that always holds and a dashed line marks a conditional one (the conditions are given per relation on the detail page). The full list of relations (34 in total, with evidence and certainty) and the definitions of the main concepts are collected on the knowledge map detail page (in Japanese). Data: JSON-LD / Turtle
2. Audit Policy Fundamentals — Do Not Mix “Basic” and “Advanced”
2.1. Understand the difference in where they live and how granular they are
Windows audit policy comes in two systems.1
- Basic audit policy: the nine category settings under “Local Policies > Audit Policy.” This is the old system that predates Windows Vista.
- Advanced audit policy (Advanced Audit Policy Configuration): the more than 40 subcategory settings under “Security Settings > Advanced Audit Policy Configuration.” Each basic category is broken down into several subcategories; the single basic “Audit account logon events” category, for example, corresponds to four subcategories on the advanced side. Enabling one category on the basic side is equivalent to enabling all of its corresponding subcategories, which records huge numbers of events you have no interest in.1
2.2. Standardize on the advanced side and prevent the basic side from overriding it
The important point is that the two systems are not compatible. Microsoft states explicitly that you should not use both basic and advanced audit policy, because audit results end up in an unexpected state.
When you apply advanced audit policy through Group Policy, the computer’s existing audit settings are cleared first and then the advanced settings are applied, and from that point on only the advanced side gives you reliable control.
In an environment that uses the advanced side, enable the security option “Audit: Force audit policy subcategory settings (Windows Vista or later) to override audit policy category settings” so that the basic side does not override your settings (it is enabled by default on standalone machines).14
flowchart TB
accTitle: The relationship between basic and advanced audit policy
accDescr: Basic audit policy and advanced audit policy are not compatible and using both leaves audit results in an unexpected state, so standardize on the advanced side and enable forcing of audit policy subcategory settings to prevent the basic side from overriding them
basic["Basic audit policy (9 categories)"] --> both{"Use both?"}
adv["Advanced audit policy (more than 40 subcategories)"] --> both
both -->|Yes| bad["Audit results in an unexpected state"]
both -->|No| unify["Standardize on the advanced side"]
unify --> force["Enable forcing of subcategory settings"]
force -.-> guard["Prevents the basic settings from overriding"]
Figure 2: The two systems are not compatible. Standardize on the advanced side and use the “force” setting to prevent the basic side from overriding it.
2.3. Use auditpol to check the policy that is actually in effect
Checking the current state takes a single command. Run it from an administrator command prompt.2
The following example shows three separate operations: displaying the current state, backing it up before a change, and restoring it. Check the display first, and take a backup before you make changes. The /restore line is what you run when you need to restore, not a step you run right after the display to check the current state.
rem List the audit settings currently in effect, per subcategory
auditpol /get /category:*
rem Back up (CSV) before a change, and restore
auditpol /backup /file:C:\logs\auditpol-backup.csv
auditpol /restore /file:C:\logs\auditpol-backup.csv
The output of auditpol is “the policy that is in effect as a result,” regardless of whether it came from GPO or from local settings. That also makes it useful for cross-checking when settings you believe you are distributing by GPO have not taken effect.
Note that changing the audit settings themselves records event 4719, so “auditing had quietly been turned off” is also traceable after the fact.12
flowchart TB
accTitle: What auditpol shows is the resulting policy
accDescr: The output of auditpol is the audit policy in effect as a result regardless of whether it came from GPO or local settings, so it can be used for cross-checking when GPO settings have not taken effect, and changes to the audit settings themselves are traceable afterwards through event 4719
gpo["Settings distributed by GPO"] --> eff["The policy in effect as a result"]
local["Local settings"] --> eff
eff --> get["List with auditpol /get"]
get -.-> diff["Usable for cross-checking when GPO has not applied"]
change["Change to the audit settings themselves"] -.-> e4719["4719 is recorded and traceable afterwards"]
Figure 3: auditpol returns “the settings in effect” regardless of their origin. Changes to the audit settings themselves remain in 4719.
3. A Decision Table for the Subcategories to Enable at Minimum
3.1. Why “enable everything” is wrong
The reason “just enable everything” is a bad move is clear. Microsoft warns, for example, that auditing the privilege use subcategories down to success produces such volumes of events that finding other entries becomes difficult, and that there is an impact on performance as well.4 The container for the log (Section 5) is finite, so the more noise you record, the fewer days of retention are left for the events you actually need. Audit design is about deciding what not to record.
flowchart TB
accTitle: Why enabling everything is a bad move
accDescr: Enabling every subcategory generates huge numbers of events that bury the events that matter in noise and affect performance, and in a finite log container it also eats into the retention span of the events you need
all["Enable every subcategory"] --> flood["Huge numbers of events"]
flood --> noise["The events that matter get buried"]
flood --> perf["Impact on performance"]
flood --> keep["Retention span gets eaten into"]
noise --> lesson["Audit design is deciding what not to record"]
perf --> lesson
keep --> lesson
Figure 4: “Enable everything” buries the events that matter. Audit design is deciding what not to record.
3.2. Start from the baseline and choose the records you need
Microsoft publishes baseline recommendations and stronger recommendations separately for workstations and servers, and that is the starting point.3 On top of that, the table below organizes things from the “at minimum, this is what I want to be able to read during an incident” perspective of a small-to-midsize environment. It is this article’s decision table, built on Microsoft’s recommendations as a starting point, not a settings list to be applied uniformly to every environment.
| Subcategory (category) | Main event IDs | What it tells you | Recommendation for small-to-midsize environments |
|---|---|---|---|
| Audit Logon (Logon/Logoff) | 4624 / 4625 | Sign-in successes and failures, logon type, source | Success + failure. Success and failure are enabled by default on Windows 10 1809 and later3 |
| Audit Special Logon (same) | 4672 / 4964 | Occurrence of a sign-in carrying administrative privilege | Success |
| Audit Account Lockout (same) | 4625 | Failed logon against an account that is locked out | Failure (4625 is a failure event; there is no success event in this subcategory)13 |
| Audit User Account Management (Account Management) | 4720 / 4726 / 4738 / 4740 | Account creation, deletion, modification, and lockout | Success + failure |
| Audit Security Group Management (same) | 4728 / 4732 / 4756 (added), 4729 / 4733 / 4757 (removed) | Members added to or removed from groups such as the administrators group (global/local/universal) | Success (there is no failure event in this subcategory)14 |
| Audit Credential Validation (Account Logon) | 4776 | Success or failure of NTLM authentication. For domain accounts this is recorded on the DC7 | Success + failure |
| Audit Kerberos Authentication Service (same, DCs only) | 4768 / 4771 | TGT issuance and pre-authentication failures such as a wrong password8 | Success + failure on DCs |
| Audit Process Creation (Detailed Tracking) | 4688 | Who started what, and from which parent process | Success. Read the cautions in Section 7 before turning on command-line logging |
| Audit Other Object Access Events (Object Access) | 4698 | Creation of scheduled tasks (a staple of attacker persistence)15 | Consider success |
| Audit Audit Policy Change (Policy Change) | 4719 | Changes to the audit settings themselves | Success + failure |
3.3. For the ones recorded in bulk, narrow the targets and the time window
Conversely, it is safer not to touch object access auditing for the file system and the registry, privilege use, or the packet filter subcategories (5152 and the like) by default. These earn their keep with a narrowly targeted SACL configuration or a time-limited window during triage; open them wide all the time and they will eat your log alive.4
flowchart TB
accTitle: How to handle the high-volume subcategories
accDescr: Object access auditing for the file system and registry, privilege use, and the packet filter subcategories eat the log alive when left wide open all the time, and earn their keep only with a narrowly targeted SACL configuration or a time-limited window during triage
heavy["High-volume subcategories"] --> use{"How do you enable them?"}
heavy -.-> ex1["Object access auditing"]
heavy -.-> ex2["Privilege use and packet filter subcategories"]
use -->|Wide open all the time| eat["Eats the log alive"]
use -->|Narrowly targeted SACL| ok1["Earns its keep"]
use -->|Time-limited during triage| ok2["Earns its keep"]
Figure 5: Do not leave object access or privilege use wide open all the time. They earn their keep only with narrowed targets and time windows.
4. How to Read the Standard Event IDs
Check three things as a set: which event it is, which machine it is left on, and which field to look at. Sign-ins start at 4.1 and 4.2, lockouts at 4.3, account changes at 4.4, and operations that were carried out at 4.5 and 4.6. In a real investigation, preserve the log first using the method in 6.3.
4.1. 4624 — Sort Successful Sign-Ins by Logon Type
4624 is “An account was successfully logged on,” and it is recorded on the machine where the logon session was created, that is, the machine that was accessed.5 Because it is recorded in large numbers, start by sorting it by logon type when you read it.5
| Logon type | Name | What it means in practice |
|---|---|---|
| 2 | Interactive | Sign-in at that PC’s console |
| 3 | Network | Access over the network (shared folders, management tools, and so on). The most common type, since it appears once per machine |
| 4 | Batch | Batch execution (scheduled tasks and the like) |
| 5 | Service | Service startup (Service Control Manager) |
| 7 | Unlock | Unlocking a locked screen |
| 8 | NetworkCleartext | A network logon where the password was passed to the authentication package in cleartext |
| 9 | NewCredentials | Duplication with different credentials (equivalent to runas /netonly) |
| 10 | RemoteInteractive | Remote Desktop |
| 11 | CachedInteractive | Sign-in with cached credentials (when the DC is unreachable) |
After sorting by type, look at the account, the source, and the privilege
The other fields to look at are the account name under “New Logon,” the source address under “Network Information,” the “Authentication Package” (NTLM or Kerberos), and the “Elevated Token” (whether this is an administrative session). If you want to track only administrative sign-ins, you can also use 4672 (special privileges assigned to new logon), which is recorded with the same logon ID.5
flowchart TB
accTitle: The procedure for sorting through 4624
accDescr: Because 4624 is recorded in large numbers, sort it first by logon type, then check the account name and source, the authentication package, and the elevated token, and cross-check administrative sign-ins against the 4672 with the same logon ID
ev["4624 successful sign-in"] --> type["Sort by logon type"]
type --> fields["Check the main fields"]
fields -.-> f1["Account name and source"]
fields -.-> f2["Authentication package"]
fields -.-> f3["Elevated token"]
fields --> admin["Tracking administrative privilege"]
admin -.-> e4672["The 4672 with the same logon ID"]
Figure 6: Sort 4624 by logon type before reading the fields. Correlate privileged sign-ins with 4672.
4.2. 4625 — Pin Down the Reason for the Failure with the Status/Sub Status Codes
4625 is “An account failed to log on,” and it is recorded on the machine where the logon was attempted.6 Rather than the wording in the “Failure Reason” field, reading the hexadecimal Status/Sub Status codes is the reliable approach. The standard set is as follows.6
First, read the reason for the failure from Status/Sub Status
- 0xC0000064: user name does not exist. A run of these in a short window is a sign of an account enumeration attack
- 0xC000006A: wrong password. A run of these against a specific account is a sign of a password guessing attack
- 0xC000006D: bad user name or authentication information
- 0xC000006F: outside the permitted hours
- 0xC0000070: from a workstation that is not permitted
- 0xC0000072: account disabled by an administrator (attempts against a former employee’s account show up here)
- 0xC000015B: the requested logon type is not granted on this machine
- 0xC0000193: expired account
- 0xC0000234: account locked out
Combine the target account, the source, and the reason for the failure
“Who, from where, and why did it fail” is pinned down by the set of three: the target account, the source (workstation name / IP address), and this code. Section 6.2 has PowerShell that extracts all three in one pass.
flowchart TB
accTitle: The flow for pinning down the reason for a 4625 failure
accDescr: Pin down the reason for a 4625 failure with the hexadecimal Status/Sub Status code, read the signs of an attack from the pattern of codes, and then identify it with the set of three that adds the target account and the source
ev["4625 failed sign-in"] --> code["Check the Sub Status code"]
code --> sign{"What is the pattern of codes?"}
sign -->|A run of 0xC0000064| enum["Sign of account enumeration"]
sign -->|A run of 0xC000006A| guess["Sign of password guessing"]
sign -->|0xC0000072| disabled["Attempt against a former employee account"]
enum --> triple["Pin it down with the set of three"]
guess --> triple
disabled --> triple
triple -.-> t1["Target account + source + code"]
Figure 7: Pin the reason down with the code, and read it together with the target account and the source as a set of three.
4.3. 4740 — The Origin of a Lockout Is the “Caller Computer Name”
Finding the origin: the caller computer name in 4740
4740 is “A user account was locked out” (the subcategory is Audit User Account Management). The field that drives this event is “Caller Computer Name,” which records which computer the logon attempt that triggered the lockout came from.16 The standard move is to identify the workstation of origin here and then sweep that workstation for old credentials still left on it.
In most cases the cause is something that keeps using old credentials after a password change: saved credentials, an RDP session left disconnected, or a service or task configured with the old password.
flowchart TB
accTitle: The standard move for investigating an account lockout
accDescr: Identify the workstation of origin from the caller computer name in 4740, and sweep that workstation for saved credentials, Remote Desktop sessions left disconnected, and services or tasks configured with the old password
ev["4740 lockout occurred"] --> caller["Check the caller computer name"]
caller --> src["Identify the workstation of origin"]
src --> sweep["Sweep for old credentials"]
sweep -.-> c1["Saved credentials"]
sweep -.-> c2["RDP sessions left disconnected"]
sweep -.-> c3["Services and tasks with the old password"]
Figure 8: Identify the origin from the “Caller Computer Name” in 4740, then sweep that workstation for old credentials.
Finding the record of the failure: look at the side that accepted it, not the origin
There is one caveat. 4625 is recorded on the computer that accepted the logon attempt. If the cause is a network logon from the workstation of origin to a file server or similar, no 4625 remains in the Security log of the workstation of origin itself; the record is left in 4625 on the destination server, or, for a domain account, in 4776 (NTLM) / 4771 (Kerberos pre-authentication failure) on the DC.78 When “there is nothing in the log on the workstation of origin,” go and look at the side that accepted it.
The flow of the investigation can be organized as: find the origin from the caller in 4740, cross-check 4625 on the destination and 4776/4771 on the DC in chronological order, then check the saved credentials, services, tasks and so on on the workstation of origin. Finding the origin and finding where the failure events are recorded are two different things.
flowchart TB
accTitle: The machines where the record of a failure remains
accDescr: A network logon failure does not remain on the workstation of origin itself but is recorded in 4625 on the destination server that accepted the logon attempt, and for a domain account the record also remains in 4776 or 4771 on the DC
src["Workstation of origin (no 4625 of its own)"] -->|Network logon| target["Destination server"]
target -.-> e4625["4625 is recorded"]
src -->|Domain account authentication| dc["Domain controller"]
dc -.-> e4776["4776 (NTLM) / 4771 (Kerberos)"]
Figure 9: 4625 remains on the side that accepted the attempt. If there is nothing on the workstation of origin, look at the destination server and the DC.
4.4. The 4720 Family — Account Creation, Modification, and Group Additions
Separate account changes from group membership changes
The account management events run in sequence: 4720 (a user account was created)17, 4726 (deleted), 4738 (changed), and then the member additions and removals on the group side.
Note that group membership changes split across event IDs by the type of group. Local groups are 4732/4733, global groups are 4728/4729, and universal groups are 4756/4757.14 Domain Admins is a global group, so an addition to it is recorded in 4728 — make 4732 alone your alert condition and you will miss the very thing you most want to see.
An unexpected addition to an administrators group is worth investigating even as a one-off
Day to day these are records of help desk work, but “a standard user was suddenly added to an administrators group” or “an account nobody knows about was created” is an immediate subject of investigation even as a single occurrence. Microsoft also lists an unexpected member addition to a privileged group as an example of an event to alert on individually.3
flowchart TB
accTitle: Group types and member addition events
accDescr: A member addition to a group splits across event IDs by the type of group, recorded in 4732 for local, 4728 for global, and 4756 for universal, so an addition to the global group Domain Admins shows up in 4728
add["Member added to a group"] --> kind{"What type of group?"}
kind -->|Local| lg["Recorded in 4732"]
kind -->|Global| gg["Recorded in 4728"]
kind -->|Universal| ug["Recorded in 4756"]
gg -.-> da["Additions to Domain Admins land here"]
lg -.-> miss["Watching only 4732 misses them"]
Figure 10: The event ID for a member addition splits by the type of group. An addition to Domain Admins is 4728.
4.5. 4688 — Process Creation. Command-Line Logging Is a Separate Switch
What process creation auditing tells you
4688 is “A new process has been created,” and on every process creation it records the account that created it, the executable path of the new process, the parent process, and the token elevation type.11 It is a high-value investigative event that can answer “who ran what on this server.”
Keeping the command line requires a separate setting and a review first
By default, however, the command-line arguments are not recorded. Only when you separately enable the Group Policy setting “Include command line in process creation events” (Administrative Templates > System > Audit Process Creation) do the arguments appear in the “Process Command Line” field of 4688.1112 It is effectively mandatory for tracking suspicious launches such as powershell -EncodedCommand ..., but enable it only after you understand the risk of secrets leaking into the log described in Section 7. Read Section 7 first, fix the places that pass secrets as arguments, and then configure it.
flowchart TB
accTitle: The relationship between 4688 and command-line logging
accDescr: Enabling process creation auditing records the account, executable path and parent process in 4688, but command-line arguments are recorded only once a separate Group Policy setting is enabled, which carries the risk of secrets appearing in plain text
audit["Enable process creation auditing"] --> ev["4688 is recorded"]
ev -.-> base["Account, path, parent process"]
ev --> args{"Do you want the arguments too?"}
args -->|Left at the default| none["Command line is empty"]
args -->|Enable the extra GPO| cmd["Arguments are recorded"]
cmd -.-> risk["Risk of secrets in plain text"]
Figure 11: Command-line logging for 4688 is a separate switch. Enabling it requires reviewing the risk of secrets leaking first.
4.6. 4698 — A Scheduled Task Was Created
4698 is “A scheduled task was created,” and it records the task name and the full XML of the task definition (including the command to run). Because registering a task is the standard technique malware uses to survive a reboot, Microsoft recommends monitoring task creation events.15 Even in environments that make heavy use of tasks for business purposes, creation is not an everyday occurrence, so the noise is on the small side.
flowchart TB
accTitle: Persistence through task registration and 4698
accDescr: Malware routinely registers scheduled tasks to survive a reboot, so monitoring the 4698 recorded on task creation lets you follow the task definition all the way down to the command it runs
mal["Malware persistence"] --> task["Register a task to survive"]
task --> ev["4698 is recorded"]
ev -.-> xml["Full XML including the command to run"]
ev --> watch["Detect it by monitoring task creation"]
watch -.-> low["Creation is not an everyday event, so little noise"]
Figure 12: Task registration, the staple technique for persistence, remains in 4698. The full definition XML lets you follow it down to the command.
To tell whether the log itself was cleared, check 1102 as well
One more to keep in mind is 1102, “The audit log was cleared.” Clearing the Security log always leaves this event, so when “the log is empty” you can tell whether it was a deliberate operation or something going wrong.18
flowchart TB
accTitle: Using 1102 to triage a cleared log
accDescr: Clearing the Security log always leaves a 1102, so when the log is empty, checking whether a 1102 is present tells you whether the clearing was an operation someone performed or something that went wrong
empty["The log is empty"] --> rule["Clearing always leaves a 1102"]
rule --> check{"Is there a 1102?"}
check -->|Yes| op["Someone performed a clear"]
check -->|No| acc["Suspect that something went wrong"]
Figure 13: Clearing the Security log always leaves a 1102. For an empty log, the presence of 1102 separates a deliberate operation from something having gone wrong.
5. Designing the Log Container — Maximum Size and Retention
5.1. When it fills up, which is lost, the old records or the new ones?
Before you add audit policies, check the vessel that has to catch them. The Security log has a maximum size and a retention mode, and in overwrite mode (the de facto standard configuration), once it reaches the maximum size new events overwrite the oldest events. In retention mode (do not overwrite), by contrast, the new events are the ones discarded once the log is full.10 Both behaviors are a cause of “the log was gone before I noticed,” so understanding the current state comes first.
5.2. Work out the capacity you need from the days actually retained
# Check the Security log container: retention mode, maximum size, current record count
Get-WinEvent -ListLog Security |
Select-Object LogName, LogMode, MaximumSizeInBytes, RecordCount
# How many days are actually retained right now (timestamp of the oldest event)
Get-WinEvent -LogName Security -Oldest -MaxEvents 1 |
Select-Object TimeCreated
Get-WinEvent -ListLog returns the log’s configuration and record count together.9 The gap between “the timestamp of the oldest event” and the present is the retention span you actually have, and if that falls short of your own requirement (the number of days you want to go back during an incident investigation) you widen the maximum size. The setting can be distributed with wevtutil sl Security /ms:<bytes> or through Group Policy.10
Think about capacity in terms of “how many days do we want to keep.” Adding audit subcategories increases event volume, so re-check the days actually retained after you change the settings. You also need an operational practice of exporting on a schedule before events are overwritten, or aggregating them onto a separate machine.
flowchart TB
accTitle: Capacity design worked backwards from the retention span
accDescr: Check the configuration and record count with the ListLog parameter of Get-WinEvent, derive the retention span actually available from the timestamp of the oldest event, and widen the maximum size if it falls short of the number of days you want to go back during an incident investigation
check["Check configuration and record count with ListLog"] --> oldest["Check the timestamp of the oldest event"]
oldest --> days["Calculate the retention span actually available"]
days --> enough{"Does it meet the requirement?"}
enough -->|It does| keep["Keep the current size"]
enough -->|It does not| grow["Widen the maximum size"]
grow -.-> how["Configure with wevtutil sl or GPO"]
Figure 14: Confirm the days actually retained, and set the maximum size by working backwards from the number of days you want to go back.
5.3. CrashOnAuditFail is not a setting that solves a capacity shortfall
Note that the security options include “Audit: Shut down system immediately if unable to log security audits” (what is commonly called CrashOnAuditFail). When it is enabled and security audits can no longer be recorded, the system stops with STOP error C0000244. It is a setting for certification requirements where the audit trail absolutely must not be dropped, and it is disabled by default.
Microsoft itself cautions that it can be turned into a DoS in which an attacker deliberately stops a server by generating huge numbers of events, so it is not something to enable casually in an ordinary small-to-midsize environment.19
flowchart TB
accTitle: Behavior when the log fills up
accDescr: The retention configuration comes in two forms, overwrite mode and do not overwrite mode, and when audits can no longer be recorded in do not overwrite mode, the separate CrashOnAuditFail setting stops the system with STOP error C0000244 if it is enabled
full["Security log reaches the maximum size"] --> mode{"What is the retention configuration?"}
mode -->|Overwrite mode| ow["The oldest events are overwritten"]
mode -->|Do not overwrite| drop["The new events are discarded"]
ow -.-> lost["Both cause the log to be gone before you notice"]
drop -.-> lost
drop --> caf{"Is CrashOnAuditFail also enabled?"}
caf -->|Yes| crash["System stops with STOP error C0000244"]
Figure 15: The retention configuration is either overwrite or discard. CrashOnAuditFail is a separate setting that halts the system when auditing cannot be recorded.
6. Investigation in Practice — Filters, Get-WinEvent, and Export
The order in which you actually work is “preserve in 6.3, then analyze in 6.1 or 6.2.” This section covers each investigative tool in turn. For a one-off, use Event Viewer; when the volume is large or the investigation repeats, use PowerShell.
6.1. Filtering in Event Viewer
For a one-off investigation, Event Viewer is enough. Open the Security log and specify the event ID (4625, for example) and the time range under “Filter Current Log.” Save conditions you look at repeatedly with “Create Custom View,” and they are one click away next time. If you want to narrow by something other than the event ID, such as a specific account, you can edit the XPath query directly on the XML tab of the filter dialog.
6.2. Extraction with Get-WinEvent
For investigations with large volumes, multiple conditions, or a recurring schedule, switch to PowerShell’s Get-WinEvent. The key is to use -FilterHashtable, which makes the filter take effect on the server side.9
flowchart TB
accTitle: Choosing between the investigative tools
accDescr: A one-off investigation is handled by the filter in Event Viewer, conditions you look at repeatedly are saved as a custom view, and investigations with large volumes, multiple conditions or a recurring schedule switch to Get-WinEvent
q{"What kind of investigation?"}
q -->|One-off| viewer["Filter in Event Viewer"]
q -->|Conditions you revisit| view["Save as a custom view"]
q -->|Large, multi-condition, scheduled| ps["Switch to Get-WinEvent"]
ps -.-> hash["Filter with FilterHashtable"]
Figure 16: Event Viewer for one-offs, custom views for repeats, Get-WinEvent when the volume is large.
Narrow by ID and time range, then pull out the target account, the source, and the reason for the failure
The first half below retrieves the 4625 events from the last 24 hours. The second half pulls the individual fields out of the XML and is an example that counts the occurrences per combination of account, Status, SubStatus, and source. The final table is not a chronological listing of individual events; it shows how many times each combination occurred, in descending order.
# Retrieve failed sign-ins (4625) from the last 24 hours
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4625
StartTime = (Get-Date).AddDays(-1)
}
# Shape "who, from where, and why" into a table
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4625
StartTime = (Get-Date).AddDays(-1)
} | ForEach-Object {
$x = [xml]$_.ToXml()
$d = @{}
$x.Event.EventData.Data | ForEach-Object { $d[$_.Name] = $_.'#text' }
[pscustomobject]@{
Time = $_.TimeCreated
Account = "$($d.TargetDomainName)\$($d.TargetUserName)"
LogonType = $d.LogonType
Source = "$($d.WorkstationName) $($d.IpAddress)"
Status = $d.Status
SubStatus = $d.SubStatus
}
} | Group-Object Account, Status, SubStatus, Source |
Sort-Object Count -Descending |
Format-Table Count, Name -AutoSize
Reuse the pattern for reading the fields you need out of the XML on other events
Once you have this pattern for pulling EventData out of an event’s XML representation, you can reuse it the same way for 4624 or 4688. The design of Get-WinEvent filtering (when to use FilterHashtable versus XPath, and how to fix a slow query) is covered in detail in “Investigating Event Logs in Practice with Get-WinEvent.”
flowchart TB
accTitle: The shaping pattern for pulling out EventData
accDescr: Convert an event retrieved with Get-WinEvent into its XML representation, pull out each EventData field and shape it into a table, and reuse this pattern the same way for 4624 and 4688 as well as 4625
get["Retrieve with Get-WinEvent"] --> xml["Convert the event to its XML representation"]
xml --> pull["Pull out EventData"]
pull --> shape["Shape into a table and aggregate"]
shape -.-> reuse["The same way for 4624 and 4688"]
Figure 17: The pattern of pulling EventData out of the XML representation into a table is reusable when the event ID changes.
6.3. Exporting with wevtutil
As a rule, the logs on the machine under investigation should be exported and secured first, before overwriting removes them.10
rem Preserve the whole Security log as evtx
wevtutil epl Security C:\logs\security-20260801.evtx
rem Export only 4625, narrowed with XPath
wevtutil epl Security C:\logs\security-4625.evtx /q:"*[System[(EventID=4625)]]"
Analyze the saved evtx on another machine
The exported .evtx can be analyzed on another machine in exactly the same way, with Get-WinEvent -Path C:\logs\security-20260801.evtx.9 The habit of preserving before analyzing is the same thinking as “secure the dump first” in a crash investigation (see “An Introduction to Collecting Windows Crash Dumps”).
flowchart TB
accTitle: The flow of preserving before analyzing
accDescr: Export and secure the Security log of the machine under investigation into an evtx file with wevtutil epl, then analyze it the same way on another machine by pointing Get-WinEvent at the path
target["Machine under investigation"] --> export["Preserve as evtx with wevtutil epl"]
export --> copy["Take it to another machine"]
copy --> analyze["Analyze with Get-WinEvent -Path"]
export -.-> note["Secure it before overwriting removes it"]
Figure 18: Preserve first, analyze second. Once it is secured as evtx you can investigate it the same way on another machine.
7. Pitfalls — Four That Are Easy to Step On in the Field
7.1. Secrets riding on the 4688 command line
Enable command-line logging and the arguments of every process go into the Security log in plain text. Microsoft states explicitly that “all users with read access to security events can read the command-line arguments for any successfully created process, and those arguments may contain sensitive data such as passwords.”12 If even one line-of-business application or script launches something like myapp.exe /user:admin /password:P@ssw0rd, that is disclosure of the secret to everyone who can read the log.
Before enabling it, find and fix the places that pass secrets as arguments. The same handling level is then required wherever the logs are preserved and forwarded.
flowchart TB
accTitle: The order for enabling command-line logging
accDescr: Before enabling command-line logging for 4688, find the line-of-business applications and scripts that pass secrets as arguments, keep the order of fixing them before enabling the setting, and require the same handling level for the preservation and forwarding destinations of the logs
audit["Find the secrets passed as arguments"] --> found{"Are there any?"}
found -->|Yes| fix["Fix the places that pass them"]
found -->|No| on["Enable command-line logging"]
fix --> on
on -.-> dest["Same handling level for preservation and forwarding"]
Figure 19: Command-line logging means “find them, fix them, then enable.” Reverse the order and you disclose the secrets.
7.2. Running without knowing the behavior when the log fills up
In overwrite mode old records silently disappear, with overwriting disabled the new events are discarded, and with CrashOnAuditFail enabled the system itself stops (Section 5).1019 The right approach is to know which behavior you have chosen and to put a mechanism in place that “collects them before they disappear” (scheduled exports or a log collection platform).
7.3. Domain controllers and workstations require different logs
4624/4625 are recorded on the machine that was accessed.56 Credential validation for a domain account (NTLM’s 4776), by contrast, is recorded on the machine that has authority over the credential, which for a domain account is a DC7, and Kerberos pre-authentication failure (4771) is recorded only on a DC.8 “There is no 4625 on the file server” does not mean “there was no attack”; you only get the whole picture once you also cross-check 4776/4771 on the DC. For how each authentication protocol actually flows, see “NTLM and Kerberos Explained with Diagrams.”
7.4. If the clocks are out of sync you cannot cross-check
Lining up logs from several machines to follow “which workstation produced a 4625 just before this 4740” assumes that the clocks on those machines agree. In a domain environment Kerberos itself sets an upper limit on clock skew (5 minutes by default), and beyond that authentication itself starts to fail.20 From an investigative standpoint, a skew of a few seconds — never mind five minutes — is enough to make you misread the order of events, so put a check of the w32time synchronization state at the very start of your investigation procedure.
Also, event timestamps are stored in UTC and displayed according to the time zone of the machine viewing them, so when you read an evtx brought over from an overseas site or from a server set to UTC, do not forget to convert the time zone.
flowchart TB
accTitle: Clock synchronization as a prerequisite for cross-checking
accDescr: An investigation that lines up logs from several machines in chronological order assumes that the clocks on those machines agree, since a skew of a few seconds is enough to make you misread the order of events and a skew beyond the default five minutes makes Kerberos authentication itself fail, so put a w32time check at the start of the procedure
merge["Cross-check logs from several machines"] --> pre["Assumes the clocks agree"]
pre --> skew{"How far are the clocks off?"}
skew -->|In agreement| ok["You can follow them chronologically"]
skew -->|A few seconds off| misread["Misreading the order of events"]
skew -->|Beyond the default 5 minutes| kerb["Kerberos authentication fails"]
pre -.-> first["Put the w32time check at the start of the procedure"]
Figure 20: Cross-checking several machines assumes the clocks are aligned. Even a few seconds of skew leads to misreading the order of events.
8. Summary
To use the Windows Security log for investigation, design three things together: the scope of what you record, the place and the fields you read, and the mechanism that preserves it.
When you are tidying up the settings
Do not mix “basic” and “advanced” audit policy; standardize on the advanced side. Check the current state with auditpol /get /category:*, and start from the decision table in Section 3, which is built around logon, account management, and process creation with Microsoft’s baseline recommendations as the starting point. “Enable everything” makes investigation harder through noise and bloat.
The log container (maximum size and retention mode) is half of audit design. Check the days actually retained, decide the size by working backwards from your requirement, and export or aggregate before events disappear. Enable command-line logging for 4688 only after reviewing the risk of secrets leaking in.
When you are investigating
Preserve first, analyze second. Secure the log with wevtutil epl, check the recording machine for each event and the clock synchronization, and only then start reading. Use the Event Viewer filter for one-offs, and Get-WinEvent -FilterHashtable for investigations that repeat.
The key points when reading are logon type for 4624, Status/Sub Status for 4625, caller computer name for 4740, and parent process and command line for 4688. Do not judge by event ID alone: confirm what information was recorded where, and cross-check the logs you need.
Related Articles
- Investigating Event Logs in Practice with Get-WinEvent — Filtering Speed Decides How Long the Investigation Takes
- Will NTLM Deprecation Stop Your Business Apps? — How to Collect Audit Logs, and the Order in Which to Kill the Dependencies
- NTLM and Kerberos Explained with Diagrams — Why Authentication “Falls Back” to NTLM
- SMB Signing and LDAP Channel Binding — Closing the “Other Half” of Your NTLM Defenses in Practice
- An Introduction to Windows Event Log and ETW — Putting Your Business App’s Logs on the OS’s Standard Mechanisms
- An Introduction to Collecting Windows Crash Dumps - WER/ProcDump/WinDbg
Related Consulting Areas
At Komura Soft LLC we handle consulting on audit policy and log design for Windows environments, investigation of “when, who, and what” based on event logs, and root-cause analysis of the trouble business applications cause around authentication and auditing. Starting from “I was asked to look at the logs, but where do I begin?” is perfectly fine.
References
-
Microsoft Learn, Advanced security auditing FAQ. On the difference between basic audit policy (the nine settings under Local Policies) and advanced audit policy, on enabling one basic category being equivalent to enabling all of its corresponding subcategories, on the two being incompatible so that using them together leaves audit results in an unexpected state and they must not be mixed, on existing audit settings being cleared when advanced policy is applied through Group Policy, on the need to enable “Audit: Force audit policy subcategory settings to override audit policy category settings,” and on minimizing event volume by identifying and narrowing to the important resources, activities, and users. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, auditpol. On the auditpol command being able to display (/get), set (/set), back up to CSV (/backup), restore (/restore), and clear (/clear) the system audit policy. ↩ ↩2
-
Microsoft Learn, System Audit Policy recommendations. On the tables of Windows defaults, baseline recommendations, and stronger recommendations for workstations and servers separately, on the recommendations being no more than a starting point that each organization should evaluate and test against its own threats and risk tolerance, on the Logon subcategory having both success and failure enabled by default on Windows 10 1809 and later, on monitoring workstations and not only servers being important, on examples of events to alert on individually such as an unexpected member addition to a privileged group, and on the idea of detecting a spike in failed logons by comparison against a baseline. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Audit: Force audit policy subcategory settings (Windows Vista or later) to override audit policy category settings. On being able to manage auditing precisely through more than 40 audit subcategories, on leaving this setting enabled being the best practice with an effective default of Enabled on clients, member servers, and DCs, and on the warning that settings which generate huge numbers of events, such as enabling all of the privilege use subcategories, make other entries harder to find in the security log and can have a significant impact on performance. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, 4624(S): An account was successfully logged on. On 4624 being recorded on the computer that was accessed when a logon session is created, on the list of logon types (2 = Interactive, 3 = Network, 4 = Batch, 5 = Service, 7 = Unlock, 8 = NetworkCleartext, 9 = NewCredentials, 10 = RemoteInteractive, 11 = CachedInteractive), on the Elevated Token flag, on the authentication package (NTLM/Kerberos/Negotiate) and the NTLM Package Name (NTLM V1/V2/LM), and on correlating with 4672 and others through the logon ID. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, 4625(F): An account failed to log on. On 4625 being recorded on the computer where the logon was attempted (the workstation, if the attempt was made at a user’s workstation), on the subcategories being Account Lockout and Logon, on the meanings of the Status/Sub Status codes (0xC0000064 = bad user name, 0xC000006A = wrong password, 0xC000006D = bad user name or authentication information, 0xC000006F = outside the permitted hours, 0xC0000070 = workstation not permitted, 0xC0000072 = disabled account, 0xC000015B = logon type not granted, 0xC0000193 = expired account, 0xC0000234 = locked out), and on a run of 0xC0000064 possibly being a sign of an account enumeration attack. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, 4776(S, F): The computer attempted to validate the credentials for an account. On 4776 being recorded every time credentials are validated through NTLM authentication, on it being recorded only on the computer that has authority over the credential, which is a domain controller for a domain account and the local computer for a local account, and on both success and failure being recorded. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, 4771(F): Kerberos pre-authentication failed. On 4771 being recorded every time the KDC fails to issue a Kerberos TGT (because of a wrong password, an expired account, and so on), and on this event being generated only on domain controllers. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Get-WinEvent (Microsoft.PowerShell.Diagnostics). On retrieving the log configuration (LogMode, MaximumSizeInBytes, RecordCount) with -ListLog, on efficient filtering by specifying LogName, Id, StartTime and so on in a hash table with -FilterHashtable, on reading a saved .evtx file with -Path, and on retrieving oldest-first with a record count using -Oldest and -MaxEvents. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, wevtutil. On setting the maximum size (/ms) and the retention mode (/rt) with set-log (sl), on a retention mode of true preserving existing events and discarding new events when the log is full while false has new events overwrite the oldest events, on exporting an event log to a file with export-log (epl) and narrowing it with an XPath query through the /q option, and on running queries with query-events (qe). ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, 4688(S): A new process has been created. On 4688 being recorded every time a new process starts, on it including the creator account, the executable path of the new process, the creator (parent) process name, and the token elevation type, and on the Process Command Line field being empty by default and only being recorded once the “Include command line in process creation events” Group Policy setting is enabled. ↩ ↩2 ↩3
-
Microsoft Learn, Command line process auditing. On command-line logging requiring both the advanced audit policy’s Audit Process Creation and “Include command line in process creation events” (Administrative Templates > System > Audit Process Creation, Not Configured by default), on the caution that once enabled the command-line information of every process is recorded in the security event log in plain text so that all users with read access can read arguments that may contain secrets such as passwords, and on event 4719 being recorded when advanced audit policy is overridden by the basic settings and on the “force” setting preventing that. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Audit Account Lockout. On the Account Lockout subcategory auditing failed logons against locked-out accounts, on the event it generates being 4625(F), on there being no success event in this subcategory so that enabling success auditing serves no purpose, and on failure auditing being recommended for every computer type. ↩
-
Microsoft Learn, Audit Security Group Management. On this subcategory auditing the creation, modification, and deletion of security groups along with member additions and removals, on the event IDs for member additions and removals splitting by group type into 4732/4733 for local groups, 4728/4729 for global groups, and 4756/4757 for universal groups, on there being domain-group-only events such as 4728, and on there being no failure event in this subcategory so that success auditing is recommended for every computer type. ↩ ↩2
-
Microsoft Learn, 4698(S): A scheduled task was created. On 4698 being recorded every time a scheduled task is created, on the subcategory being Other Object Access Events, on the task name and the full task definition XML including the command to run being recorded, and on monitoring task creation events being recommended especially on important machines because malware routinely uses tasks for persistence across reboots. ↩ ↩2
-
Microsoft Learn, 4740(S): A user account was locked out. On 4740 being recorded every time a user account is locked out, on the subcategory being User Account Management, and on the Caller Computer Name field recording the name of the computer from which the logon attempt that caused the lockout was received. ↩
-
Microsoft Learn, 4720(S): A user account was created. On 4720 being recorded on domain controllers, member servers, and workstations every time a new user object is created, and on the subcategory being User Account Management. ↩
-
Microsoft Learn, 1102(S): The audit log was cleared. On event 1102 being recorded every time the Windows security audit log is cleared. ↩
-
Microsoft Learn, Audit: Shut down system immediately if unable to log security audits. On the system stopping with the STOP message C0000244 {Audit Failed} when security audits cannot be logged while this setting is enabled, on the default value being Disabled, on it being convertible into a DoS that deliberately forces a shutdown by generating huge numbers of security events, and on the risk that application data becomes unusable because of the abrupt halt. ↩ ↩2
-
Microsoft Learn, Maximum tolerance for computer clock synchronization. On Kerberos v5 using timestamps as a countermeasure against replay attacks, so that a maximum tolerance (5 minutes both by default and by recommendation) is set for clock skew between the client and the domain controller, beyond which the timestamp is not considered authentic. ↩
Related Articles
Recent articles sharing the same tags. Deepen your understanding with closely related topics.
A Practical Guide to Windows LAPS — Retiring the Shared Local Administrator Password Across All PCs
A shared local admin password lets one compromised PC spread to all via Pass-the-Hash. This guide covers Windows LAPS rotation, AD/Entra ...
The Windows Certificate Store in Practice — User or Computer, Which Should You Use?
Should a client certificate go in the user or computer store? A practical guide to certmgr.msc vs certlm.msc, private key permissions, an...
The Windows Firewall and Business Applications — Register Inbound Rules From the Installer
When a Windows business app cannot communicate on site, triage inbound rules, listening, profiles, and managed policy. Covers rule design...
SMB Signing and LDAP Channel Binding — Closing the "Other Half" of NTLM Defense in Practice
SMB signing and LDAP signing/channel binding limit relay damage while you retire NTLM. We cover OS defaults, audit events, enforcement, a...
Will NTLM Deprecation Stop Your Business Apps? — How to Collect Audit Logs, and the Order in Which to Kill Dependencies
This article covers how to find where Windows and business apps depend on NTLM: audit policies, NTLM/Operational events 8001-8004, causes...
Related Topics
These topic pages place the article in a broader service and decision context.
Windows Technical Topics
Topic hub for KomuraSoft LLC's Windows development, investigation, and legacy-asset articles.
Where This Topic Connects
This article connects naturally to the following service pages.
Windows App Development
We support Windows desktop applications that involve resident processing, device integration, operational logging, and maintainable structure.
Frequently Asked Questions
Common questions about the topic of this article.
- We have not configured any audit policy, so why are 4624 and 4625 recorded in the Security log?
- Because Windows has audit subcategories that are enabled by default. The "Audit Logon" subcategory, for example, has both success and failure enabled by default on Windows 10 version 1809 and later, so 4624 (success) and 4625 (failure) are recorded even if you configure nothing. With the defaults left as they are, though, many of the events you end up wanting during an investigation are not recorded, such as credential validation (4776) and process creation (4688). You can check what is enabled in your own environment with auditpol /get /category:*. From there, the standard practice is to explicitly enable the missing subcategories on the advanced audit policy side.
- I want to investigate a failed sign-in, but I cannot find 4625 in the Security log on the server in question. Where should I look?
- First, confirm the principle that 4625 is recorded on "the computer where the logon was attempted." For a failed sign-in on a user's workstation that is the workstation; for a failed access attempt against a file server that is the file server. Next, use auditpol /get /category:* to check whether failure auditing is enabled for the "Audit Logon" subcategory. For a domain account, the record often remains instead in credential validation (4776) or Kerberos pre-authentication failure (4771) on the domain controller, and when you cannot identify the workstation, starting from the DC side is often the faster route. If you still find nothing, check whether older entries have already been lost to overwriting (compare the log's maximum size against the timestamp of the oldest event).
- Should we enable command-line logging for process creation (4688)?
- Its investigative value is very high, but it is a setting you should enable only after you understand the risk. Once enabled, the command-line arguments of every process are recorded in the Security log in plain text. If even one script or line-of-business application passes a password or an API key on the command line, that secret becomes visible to everyone who can read the Security log. Microsoft itself documents this caution explicitly. We recommend this order: first check whether your own scripts pass secrets as command-line arguments, fix the places that do, and only then enable the setting.
- How large should the Security log's maximum size be?
- The sound approach is to work backwards from "how many days do we want to keep on hand," and there is no universal number. You can check the current setting and how it is actually behaving with Get-WinEvent -ListLog Security, and the gap between the timestamp of the oldest event and the current time is "how many days are actually retained right now." Adding audit subcategories increases event volume, so always re-check this actual retention span after you change settings. Incident response not infrequently needs logs from weeks or months ago, so it is reassuring to export the log regularly before overwriting removes it, or to aggregate it onto a separate machine with a log collection mechanism.
- How do I investigate the cause of an account lockout (4740)?
- The "Caller Computer Name" field of the 4740 event is the first clue. It records the computer that originated the failed logon attempt that triggered the lockout. Note, however, that the failure record itself (4625) remains on the side that accepted the logon attempt, not on the machine of origin. If it came from a network logon, follow 4625 on the destination server, or 4776/4771 on the domain controller for a domain account, in chronological order. Then, on the workstation you have identified as the origin, sweep for anything still holding old credentials after the password change: saved credentials, Remote Desktop sessions left disconnected, and services or scheduled tasks configured with the old password. If lockouts keep recurring, also check whether clock synchronization has drifted.