Windows audit policy that detections can rely on
A detection rule for a new member in Domain Admins is three lines long. It is also useless if the domain controllers never record 4728, and on many networks they do not, because nobody enabled the subcategory that produces it. Windows ships with an audit policy designed to keep logs small, not to answer an investigator’s questions.
This article is the second step after the log source inventory: before writing rules for Windows, make sure Windows writes the events those rules read. It covers a baseline for domain controllers and member machines, the two settings that make the baseline actually apply, the subcategories that cost the most volume, and a read-only script that compares a machine with the baseline: windows-audit-policy-check.ps1.
What you need before you start
- Group Policy rights to create a GPO and link it to the Domain Controllers OU and to the OUs with servers and workstations. A separate GPO is easier to audit than edits to Default Domain Controllers Policy.
- An idea of your volume budget. Several subcategories below roughly double the Security log on a busy domain controller. If you pay per gigabyte in your SIEM, measure before and after (the inventory has a field for it).
- Forwarding in place, or planned. A richer audit policy with a small local log means events overwrite each other faster. That is fine if they are forwarded, and a loss if they are not.
Two settings that decide whether the baseline applies
Windows has two audit policy models: the nine legacy categories under Security Settings > Local Policies > Audit Policy, and more than 50 subcategories under Advanced Audit Policy Configuration. Mixing them produces results that are hard to predict, and Microsoft advises against it.
- Use only Advanced Audit Policy Configuration. In the GPO: Computer Configuration > Policies > Windows Settings > Security Settings > Advanced Audit Policy Configuration > Audit Policies. Leave the legacy categories as Not Defined.
- Enable “Audit: Force audit policy subcategory settings (Windows Vista or later) to override audit policy category settings” under Security Options. Without it, a legacy category set somewhere else can override your subcategories. The script checks the registry value behind this setting,
SCENoApplyLegacyAuditPolicy.
The second setting that changes what detections can see is not an audit subcategory at all: “Include command line in process creation events”, under Administrative Templates > System > Audit Process Creation. Without it, process creation events (4688) say that powershell.exe ran, not what it ran. Microsoft documents it in Command line process auditing.
The baseline
This is a starting point that covers the identity, execution and persistence events most Windows detections need. It is close to, but not identical with, Microsoft’s audit policy recommendations; where we differ, it is usually to keep volume down.
Every Windows machine
| Subcategory | Setting | Events that rules commonly use |
|---|---|---|
| Credential Validation | Success and Failure | 4776 (NTLM validation) |
| Security Group Management | Success | 4728/4732/4756 member added, 4729/4733/4757 removed |
| User Account Management | Success and Failure | 4720 created, 4722 enabled, 4724 password reset, 4725 disabled, 4726 deleted, 4738 changed, 4740 locked out |
| Process Creation | Success | 4688 |
| Account Lockout | Failure | 4625 for logons refused because the account is locked |
| Logon | Success and Failure | 4624, 4625, 4648 (explicit credentials) |
| Logoff | Success | 4634, 4647 |
| Other Logon/Logoff Events | Success and Failure | 4778/4779 RDP session reconnect and disconnect |
| Special Logon | Success | 4672 (privileged logon) |
| Other Object Access Events | Success and Failure | 4698 scheduled task created, 4699 deleted, 4702 updated |
| Audit Policy Change | Success | 4719 (audit policy changed) |
| Authentication Policy Change | Success | 4706/4707 trusts, 4739 domain policy changed |
| Security State Change | Success | 4608 startup, 4616 system time changed |
| Security System Extension | Success | 4697 service installed |
| System Integrity | Success and Failure | 4612 (audit events dropped) and other integrity failures |
Domain controllers only
| Subcategory | Setting | Events that rules commonly use |
|---|---|---|
| Kerberos Authentication Service | Success and Failure | 4768 ticket-granting ticket, 4771 pre-authentication failed |
| Kerberos Service Ticket Operations | Success and Failure | 4769 service ticket requested |
| Computer Account Management | Success | 4741 created, 4742 changed, 4743 deleted |
| Other Account Management Events | Success | 4782 password hash accessed |
| Directory Service Access | Success | 4662 (operation on an object) |
| Directory Service Changes | Success | 5136 modified, 5137 created, 5141 deleted |
Two of these deserve a warning. Directory Service Access and Directory Service Changes only record operations on objects whose System Access Control List (SACL) asks for auditing. Enabling the subcategory is necessary but not sufficient: the SACLs decide what you see, and they belong in a separate change.
One event needs nothing at all: 1102, The audit log was cleared, is always written to the Security log when someone clears it. Other logs report the same in the System log as 104.
What is deliberately not in the baseline
- Sensitive Privilege Use (
4673,4674). High volume and hard to read; enable it when a specific detection needs it. - File Share and Detailed File Share (
5140,5145). Useful on file servers, very noisy elsewhere.ADAPTper server role. - Process Termination (
4689). Rarely worth its volume for detection. - Filtering Platform Connection (
5156). Records every allowed connection through Windows Firewall; very large. A network sensor or EDR does this job better.
Where the volume goes
On domain controllers, three subcategories produce most of the events: Logon, Kerberos Service Ticket Operations and Credential Validation. They are also the ones identity detections depend on — password spraying, Kerberoasting, unusual service ticket requests — so the answer is rarely to turn them off. The answer is to size the log and the SIEM for them, and to filter known noise at the collector rather than at the source.
On servers, Process Creation grows with automation: a monitoring agent that starts a script every minute produces 1,440 4688 events per day on that host alone. Find those parents and filter them in the SIEM, with a comment that says why.
The Security log itself has a maximum size, set by Administrative Templates > Windows Components > Event Log Service > Security > Specify the maximum log file size (KB). When it is full, the default behavior is to overwrite the oldest events. Check what a machine has with wevtutil gl Security, and how far back it actually reaches with the script below.
Checking a machine against the baseline
windows-audit-policy-check.ps1 is read-only. It runs auditpol /get /category:* /r, compares each subcategory with the baseline for the machine’s role, checks the two registry values behind the settings above, and reports the Security log size, mode and how many hours it reaches back.
# Elevated PowerShell on the machine you want to check
.\windows-audit-policy-check.ps1 | Format-Table -AutoSize
# On a domain controller, require 48 hours of local history
.\windows-audit-policy-check.ps1 -Role DomainController -MinLocalHours 48
The output is one row per check with a status: OK, MISSING (the setting is below the baseline), LOW (the local log reaches back fewer hours than you asked for), CHECK (needs a human look) or INFO. Pipe it to Export-Csv to compare machines.
Subcategory names are matched in English. On a localized Windows, the names in auditpol output are translated and the script reports not found; compare by GUID instead, using auditpol /list /subcategory:* /v.
Testing that events arrive
The script proves the configuration. It does not prove that the events reach your SIEM. For three subcategories, generate one harmless event each and look for it centrally, by account name:
- User Account Management: create and delete a test account (
net user ew-audit-test <password> /add, then/delete). Expect4720and4726on the machine where the account lives — on a domain controller for a domain account. - Process Creation: run
cmd.exe /c echo ew-audit-test. Expect4688withew-audit-testin Process Command Line. If the field is empty, the command-line setting did not apply. - Other Object Access Events: create and delete a scheduled task (
schtasks /create /tn ew-audit-test /tr notepad.exe /sc once /st 23:59, thenschtasks /delete /tn ew-audit-test /f). Expect4698and4699.
Agree the test with whoever watches the SIEM first. Account creation and scheduled tasks are exactly what good detections alert on.
Limitations
- An audit policy records what Windows decides to log. It does not record what a process does in memory, and
4688carries no parent command line or file hash. Endpoint telemetry such as Sysmon, covered later in this series, fills part of that gap. - An administrator can change the audit policy.
4719records it, so alert on4719from any account that is not your Group Policy process. - Local Group Policy and
auditpol /setchanges on a single machine are overwritten at the next Group Policy refresh if a domain GPO sets the same subcategory, and win if it does not. The script shows the effective result, not where it came from; usegpresult /hfor that. - We have not measured volume for your environment. The volume notes above describe which subcategories grow fastest, not by how much.
Adapting this to your environment
ADAPTthe baseline per role. File servers, Remote Desktop hosts and Certificate Services servers each need extra subcategories; workstations may not need all of the server set.ADAPT-MinLocalHoursto how long forwarding can realistically be down before someone notices — a weekend is a common answer.ADAPTthe SIEM side: filter known high-volume parents and service accounts at the collector, and write each filter down with its reason.
The check script is windows-audit-policy-check.ps1 (MIT). Record the result for each machine role in your log source inventory. If something here is wrong, write to hello@entropywatch.dev and we will correct it in the open.