# Beneath the Dashboard: What Your SIEM Actually Sees in the Windows Security Log

> Advanced Audit Policy, SACLs, Windows Event Forwarding, and log anti-forensics: the native foundation every Windows SIEM assumes but few configure well.

*Published: 2026-07-02*
*Canonical: https://paragmali.com/blog/beneath-the-dashboard-what-your-siem-actually-sees-in-the-wi*
*© Parag Mali. All rights reserved.*

---
<TLDR>
Every Windows SIEM ingests the `Security` event log, but that log holds only what **Advanced Audit Policy subcategories** and **SACLs** were configured to write. By default the `SCENoApplyLegacyAuditPolicy` force setting makes the *legacy* audit toggles silently do nothing [@ms-force-setting], so a host can look configured while auditing almost nothing. **Windows Event Forwarding** getting the log off-box is the one control that survives an attacker clearing it (Event ID 1102, T1685.005 [@mitre-t1685-005]) or silencing it with a thread-termination tool like Phant0m (T1685.001 [@mitre-t1685-001, @phant0m]). Protected Event Logging is confidentiality, not tamper-resistance [@ms-about-logging]. Your SIEM is only as good as the audit policy and forwarding beneath it.
</TLDR>

## 1. The Dashboard Was Green

The dashboard was green. Three weeks after the domain was fully compromised -- a new domain administrator, a scheduled task planted on the crown-jewel file server, lateral movement across a dozen hosts -- the Sentinel console still showed nothing but healthy endpoints and a flat event graph. The SIEM was not broken, and it was not lying. It was faithfully displaying an empty log.

How does a fully deployed, well-funded SIEM see a three-week domain takeover as silence? The post-mortem found three answers, and none of them lived in the SIEM.

**First, the event that would have caught the lateral movement was never written.** The administrator had, years earlier, ticked the *basic* Object Access setting in a Group Policy Object, exactly as an older runbook instructed. On every modern Windows host that toggle does nothing, because the `SCENoApplyLegacyAuditPolicy` "force" setting is enabled by default and makes the fine-grained subcategory surface authoritatively win. Microsoft states the consequence plainly: "the Group Policy audit setting is ignored in favor of the custom policy setting" [@ms-force-setting]. The log looked configured. It was auditing almost nothing.

**Second, the one object that mattered had no SACL.** Auditing a specific file, key, or directory requires an audit entry -- an ACE -- in that object's System Access Control List [@ms-acl-sacl]. The file server that held the crown jewels carried none, so the access that mattered generated no record even where the subcategory was on.

**Third, on the way out, the attacker silenced what little remained.** They ran `wevtutil cl security`, which clears the Security log and emits Event ID 1102, "the audit log was cleared" [@ms-appendix-l] -- MITRE ATT&CK technique T1685.005 [@mitre-t1685-005]. Then, on a couple of noisy hosts, they went quieter still and terminated the Event Log service worker threads with a Phant0m-style tool, so the service reported "Running" while recording nothing [@phant0m].

Every one of those three failures sits *beneath* the SIEM. Not one is a detection-rule problem, a correlation problem, or a dashboard problem. They are audit-policy and forwarding problems in the plumbing the SIEM silently assumes is correct.

<Mermaid caption="The native pipeline in three layers: production decides what is written, collection decides what survives and ships, and the SIEM shows only what reaches its table. The attacker aims at the left two layers, never the dashboard.">
flowchart LR
    subgraph PROD["Production - what gets written"]
      A["Audit policy subcategories"]
      B["SACL audit ACEs"]
    end
    subgraph COLL["Collection - what survives and ships"]
      D["WEF and WEC"]
      E["AMA plus DCR or Splunk UF"]
    end
    subgraph SIEM["SIEM - what you actually see"]
      F["SecurityEvent table and dashboard"]
    end
    A --> D
    B --> D
    D --> E
    E --> F
    ATK["Attacker aims here"] -.-> PROD
    ATK -.-> COLL
</Mermaid>

> **Key idea:** Your SIEM is only as good as the audit policy and forwarding config beneath it, and attackers know exactly which events to silence.

That single sentence is the argument of this article, and everything below is its proof. The expensive detection stack at the top rests on a cheap, native, badly configured foundation, and the adversary attacks the foundation, not the dashboard.

<PullQuote>
The board was never lying. It faithfully showed an empty log -- and an empty log is exactly what the attacker worked to produce.
</PullQuote>

> **Note:** "No alerts" and "nothing happened" are not the same statement. On a Windows estate, the distance between them is measured in audit-policy subcategories, SACLs, and forwarding subscriptions -- every one of which can be misconfigured into silence without a single error message.

To understand why the log was empty -- and why an attacker can empty it on purpose -- we have to go back to a 1980s trust requirement that demanded selective auditing two decades before Windows could deliver it.

## 2. Auditing as a Trust Requirement

Why does Windows have a Security log at all? The answer is not a product decision. It is a 1985 United States Department of Defense standard.

The *Trusted Computer System Evaluation Criteria* -- DoD 5200.28-STD, universally known as the "Orange Book" -- codified fundamental security requirements for systems trusted to handle sensitive data.

Requirement 4 was **Accountability**, and its wording reads like a specification written for a subsystem that would not exist for twenty years: "Audit information must be selectively kept and protected so that actions affecting security can be traced to the responsible party... The capability to select the audit events to be recorded is necessary to minimize the expense of auditing and to allow efficient analysis. Audit data must be protected from modification and unauthorized destruction" [@tcsec-orangebook].

Read that clause slowly, because the rest of this article is Windows spending forty years trying to satisfy it. Four testable demands hide inside it: auditing must be **selective** (you choose which events are recorded), **attributable** (each record ties an action to a principal), **protected** (the trail resists modification and destruction), and **analyzable** (the volume stays low enough to actually review). A system earned the **C2 "Controlled Access Protection"** class only if it met all four. Accountability was not a feature. It was a rating requirement.

<Aside label="The clause that saw the future">
"The capability to select the audit events to be recorded" anticipates, by two decades, both SACL object-level filtering and Advanced Audit Policy subcategories [@tcsec-orangebook]. Coarse "audit everything" was never the intent. Selectivity was baked into the founding requirement, and every generation of Windows auditing is judged by how completely it delivers it.
</Aside>

Windows NT was architected to meet C2, and in 1993 NT 3.1 shipped the machinery [@custer-inside-nt]. At its heart sat a kernel component that decides who may touch what.

<Definition term="Security Reference Monitor (SRM)">
The kernel-mode component of Windows that mediates access to every securable object. When code attempts an operation, the SRM performs the access check against the object's security descriptor -- and, when auditing is configured, the SRM *generates* the audit record. It does not write to disk itself: the Local Security Authority Subsystem (LSASS) and the Event Log service carry the record the rest of the way to the Security event log.
</Definition>

Every securable object in NT carries a **security descriptor** holding two access control lists: a DACL that grants or denies access, and a SACL that generates audit records. The distinction is the whole game.

<Definition term="System Access Control List (SACL)">
The audit half of a security descriptor. Microsoft's still-current definition: "A system access control list (SACL) allows administrators to log attempts to access a secured object. Each ACE specifies the types of access attempts by a specified trustee that cause the system to generate a record in the security event log" [@ms-acl-sacl]. A DACL controls access; a SACL controls auditing. They are independent lists.
</Definition>

This design earned its badge. Windows NT 3.5 with Service Pack 3 received a TCSEC C2 rating in mid-1995 -- and here the story plants its first irony. The rating applied to a **standalone, non-networked** configuration [@routefifty-nt-critic]. The evaluation that validated NT's audit and accountability design explicitly excluded the network, the very surface almost every later attack would use. As one contemporaneous critique put it, a system may offer C2 auditing, but that does not mean the audit logs are useful, or that anyone reads them [@boran-os-overview].

<Sidenote>The exact month of the NT 3.5 C2 rating is secondary-sourced. The contemporaneous reporting says July 1995 [@routefifty-nt-critic]; the authoritative NCSC Evaluated Products List entry is an archival record not readily fetchable today, so treat "mid-1995" as the safe form.</Sidenote>

NT shipped the machinery for accountability: a reference monitor, a SACL on every object, and a protected log. But the way it *exposed* that machinery to administrators -- as a handful of coarse switches -- would betray the exact selectivity the Orange Book demanded. To see how, watch what happens when you try to audit one registry key.

## 3. The Scalpel Gated Behind the Blunt Valve

You want to catch writes to one registry key. Simple, right? Watch what actually happens on Windows through Server 2003.

Auditing in that era was governed by a short list of **basic categories** under `Security Settings\Local Policies\Audit Policy`, each a single Success/Failure switch covering a broad class of behavior [@ms-audit-policy].

The exact count is worth getting right, because it dates the pain precisely. Windows 2000 exposed **nine** basic categories [@ms-audit-policy-reference], and exactly two of them were new in that release: *Audit account logon events*, which records authentication at the validating authority such as the Kerberos ticket exchange on a domain controller [@ms-basic-account-logon], and *Audit directory service access*, which records access to an Active Directory object that carries its own SACL [@ms-basic-ds-access]. Subtract those two Windows 2000 additions and the earlier Windows NT family -- 3.1, 3.5, and 4.0 -- is left with the remaining **seven**. That nine-category surface persisted essentially unchanged through Windows XP and Server 2003.

| Basic category | Present since | Splits later into subcategories such as |
|---|---|---|
| Logon | NT 3.1 | Logon, Logoff, Account Lockout, Special Logon |
| Object Access | NT 3.1 | File System, Registry, SAM, Detailed File Share, Other Object Access |
| Account Management | NT 3.1 | User Account, Security Group, Computer Account Management |
| Privilege Use | NT 3.1 | Sensitive and Non-Sensitive Privilege Use |
| Process Tracking | NT 3.1 | Process Creation, Process Termination, RPC Events, DPAPI Activity |
| Policy Change | NT 3.1 | Audit Policy Change, Authentication Policy Change |
| System | NT 3.1 | Security State Change, Security System Extension, System Integrity |
| Account Logon | Windows 2000 | Credential Validation, Kerberos Authentication Service, Kerberos Service Ticket Operations, Other Account Logon Events |
| Directory Service Access | Windows 2000 | Directory Service Access, Directory Service Changes |

Read the right-hand column and the coarseness jumps out: those subcategory names did not exist yet [@ms-adv-audit-settings]. Each row was a single switch with no dial between "off" and "all of it." Microsoft's own comparison makes the scale concrete: "the basic audit policy provides a single setting for account sign-in, and the advanced audit policy provides four. Enabling the single basic setting would be the equivalent of setting all four advanced settings" [@ms-adv-audit-faq]. One blunt switch stood in for what later became a panel of precise ones.

Now return to that one registry key. To audit it you enable the **Object Access** category -- the global master valve. Every audited object access on the machine floods in with it. On a busy server, ordinary registry and file churn buries your one relevant event among tens of thousands. The Security log is a fixed-size ring that overwrites the oldest events when full [@ms-eventlog-key], so on a busy domain controller it can roll over quickly, destroying earlier evidence. Performance suffers. So the administrator does the rational thing and turns Object Access back off -- and now the key is completely unaudited.

The tragedy is that the object-level precision *existed*. It just could not be reached affordably.

<Definition term="Audit ACE">
An access control entry inside a SACL, essentially the tuple `{trustee SID, access mask, success or failure flags}`. It is the object-level scalpel: it can say "record when this principal writes to this key" [@ms-acl-sacl]. But an audit ACE fires only if the governing Object Access category is also enabled -- the scalpel is useless while the valve is shut.
</Definition>

So the SACL is a perfect scalpel gated behind a blunt, all-or-nothing valve. Turn the valve on and you drown; turn it off and the scalpel cuts nothing. Grade this against the Orange Book: it fails the **selective** clause operationally. C2 demanded selectivity precisely "to minimize the expense of auditing" [@tcsec-orangebook], and the coarse-category model made selectivity so expensive that administrators opted out entirely. They turned auditing *down* -- the exact opposite of what the standard asked for.

> **Note:** For more than a decade the SACL gave Windows genuine object-level selectivity, and almost nobody could afford to use it. The precision was real, but it was locked behind a category switch that was all-or-nothing. The lesson the next generation had to absorb: granularity at the *object* is worthless without granularity at the *policy*. You need both, or you get noise, and noise makes defenders switch auditing off.

The problem, then, was never the SACL. It was the coarse category gating it. What if each of those categories could be subdivided, so an administrator could enable exactly the behavior they cared about -- "the logon events I want" without "every logoff, every IPsec negotiation, every handle" -- and pay only for that? In Windows Vista, Microsoft did exactly that. And then it did something subtler, and more dangerous.

## 4. Subcategories, and a Trap Enabled by Default

In Windows Vista and Server 2008, Microsoft cut the coarse categories into pieces. The auditable set "expanded from nine to 53" fine-grained **subcategories**, grouped under about ten categories, so that for the first time an administrator could audit "Logon" without "Logoff," or "Process Creation" without the rest of Detailed Tracking [@ms-audit-policy-reference]. The stated rationale is exactly the Orange Book's selective clause, arriving twenty years late: the subcategories let you "select only the behaviors that you want to monitor" and exclude those that "create an excessive number of log entries" [@ms-adv-audit-settings].

There is a release nuance worth pinning down, because getting it wrong misdates the whole capability. The subcategories shipped in Vista and Server 2008, but at first they were *not integrated with Group Policy* and "could only be deployed by using logon scripts generated with the Auditpol.exe command-line tool." The centralized `Security Settings\Advanced Audit Policy Configuration` node in Group Policy arrived one release later: "Starting in Windows Server 2008 R2 and Windows 7, all auditing capabilities are integrated with Group Policy" [@ms-audit-policy-reference].

<Definition term="Advanced Audit Policy subcategory">
One of the fine-grained audit switches -- Microsoft describes "over 40," and the exact total ran to 53 at introduction and grew across releases -- that superseded the coarse basic categories [@ms-force-setting, @ms-audit-policy-reference]. Each subcategory can be set to audit Success, Failure, both, or neither, so policy volume becomes tunable downward to only the behaviors that matter [@ms-adv-audit-settings].
</Definition>

That was the breakthrough. The subtler move -- the one that produced the empty log in our post-mortem -- was how Microsoft made the two surfaces coexist. If a host has both a legacy basic policy and a modern subcategory policy, which wins? Microsoft answered with a precedence switch, and then turned it on for everyone.

<Definition term="SCENoApplyLegacyAuditPolicy (the force setting)">
The registry value behind the security option "Audit: Force audit policy subcategory settings (Windows Vista or later) to override audit policy category settings." When enabled -- the effective default on client, member server, and domain controller -- the subcategory surface authoritatively wins and legacy category policy is not applied [@ms-force-setting]. It "will override audit policy settings under `Security Settings\Local Policies\Audit Policy`" [@ms-audit-policy-reference].
</Definition>

The intent was benign: stop the two surfaces from silently fighting by declaring a deterministic winner. The side effect is a footgun. On a default modern host, an administrator who sets a *basic* category -- from muscle memory, a stale runbook, or an inherited GPO -- watches it do absolutely nothing.

<PullQuote>
"...the Group Policy audit setting is ignored in favor of the custom policy setting." -- Microsoft, describing what happens to a legacy audit toggle once the force setting is in effect [@ms-force-setting]
</PullQuote>

The intended audit never happens, no error is raised, and the host looks configured while auditing whatever the subcategories say -- which, if nobody set them, is nothing. This is a misconfiguration that is invisible by design.

<Mermaid caption="Why a basic audit toggle silently no-ops on a modern host: with the force setting enabled by default, the subcategory surface is authoritative and the legacy toggle is ignored.">
flowchart TD
    Start["Admin sets an audit option in GPO"] --> Q&#123;"Is SCENoApplyLegacyAuditPolicy enabled?"&#125;
    Q -->|Yes the default| Sub["Subcategory settings are authoritative"]
    Q -->|No| Basic["Legacy category settings apply"]
    Sub --> NoOp["A basic category toggle is silently ignored"]
    Basic --> Mix["Basic and advanced can conflict, unexpected results"]
    NoOp --> Verify["Verify effective policy with auditpol"]
</Mermaid>

Here is the same logic as a tiny resolver you can run. It models the exact conditions of the breach: a basic toggle set, the force setting on, and nothing configured at the subcategory level.

<RunnableCode lang="js" title="The force-setting no-op, in miniature">{`
// How Windows resolves effective audit policy (simplified)
const forceSetting = "Enabled";              // SCENoApplyLegacyAuditPolicy, default on
const basicPolicy = { "Object Access": "Success" }; // what the admin ticked in GPO
const subcategoryPolicy = {};                // what was set at subcategory level: nothing

function effectiveAuditPolicy(force, basic, subcats) {
  // When the force setting is on, the subcategory surface wins outright.
  return force === "Enabled" ? subcats : basic;
}

const effective = effectiveAuditPolicy(forceSetting, basicPolicy, subcategoryPolicy);
const auditing = Object.keys(effective);

console.log("Admin configured :", Object.keys(basicPolicy).join(", "));
console.log("Host is auditing :", auditing.length ? auditing.join(", ") : "nothing");
// Host is auditing : nothing
`}</RunnableCode>

Because both surfaces can be present, mixing them without understanding the precedence is unsafe: Microsoft warns it "can cause unexpected results," so the supported guidance collapses to "pick advanced, and force it" [@ms-adv-audit-faq, @ms-audit-policy-reference]. You configure subcategories with `auditpol.exe`, an exported GPO CSV (`audit.csv`), or `secpol.msc`, and -- this is the load-bearing habit -- you verify what is *actually* in effect with `auditpol /get /category:*`, not the GPO you believe you set [@ms-auditpol].

> **Note:** On any supported Windows host, assume the force setting is on. A basic-category toggle is a silent no-op there. The only trustworthy answer to "what is this host auditing?" comes from `auditpol /get /category:*` run on the host itself [@ms-auditpol, @ms-force-setting].

The Vista release also rebuilt the event log on [Event Tracing for Windows](/blog/etw-how-windows-2000s-performance-hack-became-the-edr-substr/), moving the Security channel onto the `Microsoft-Windows-Security-Auditing` provider, GUID `{54849625-5478-4994-A5BA-3E3B0328C30D}`, and renumbering the event IDs wholesale [@ms-event-4688]. That timeline is worth seeing whole.

<Mermaid caption="The generational arc: a 1985 trust requirement, answered one failure at a time, from the Orange Book to cloud-native collection.">
timeline
    title Forty years of learning to watch
    1985 : TCSEC C2 demands selective, attributable, protected auditing
    1993 : Windows NT ships the SRM, SACLs, and the Security log
    2000 : Windows 2000 raises the basic categories to nine
    2006-2008 : Vista and Server 2008 add subcategories, settable only via auditpol
    2008 : Windows Event Forwarding ships to move the log off the box
    2009 : Windows 7 and Server 2008 R2 add the Advanced Audit Policy GPO node
    2015 : WEF reframed as blue-team doctrine, and KB3004375 backports to Windows 7 the Event 4688 command line added in 2013
    2024-2027 : Cloud-native AMA and Data Collection Rules feed Sentinel
</Mermaid>

The log can finally be selective. But selective about *what*? To read it -- or to notice its silence -- you have to know which event ID rides which subcategory, and which ones an attacker prays you never enabled.

## 5. Eight Numbers That Read a Breach

Learn to read eight event IDs -- and to name the subcategory each one rides -- and you can read a Windows intrusion end to end. The `Security` channel, backed by the `Microsoft-Windows-Security-Auditing` provider [@ms-event-4688], carries hundreds of event types, but a small set does most of the detective work. Here is the load-bearing set, each anchored to the subcategory that must be enabled for it to exist and to the adversary behavior it exposes.

| Event ID | What it records | Gating subcategory | What it reveals to a hunter |
|---|---|---|---|
| 4624 | Successful logon | Logon/Logoff, Logon | Session start; the logon type separates interactive from network (type 3) and remote-interactive (type 10) [@ms-event-4624] |
| 4625 | Failed logon | Logon/Logoff, Logon | Password spraying and brute force |
| 4672 | Special privileges assigned at logon | Logon/Logoff, Special Logon | An administrator-equivalent session (privileges such as SeDebugPrivilege) |
| 4688 | New process created, with command line | Detailed Tracking, Process Creation | Execution, living-off-the-land binaries, encoded command lines |
| 4698 | Scheduled task created | Object Access, Other Object Access Events | Persistence and lateral movement |
| 4720 | User account created | Account Management, User Account Management | A rogue account being stood up |
| 4768 | Kerberos authentication ticket requested | Account Logon, Kerberos Authentication Service | Initial domain authentication, recorded on the domain controller |
| 4769 | Kerberos service ticket requested | Account Logon, Kerberos Service Ticket Operations | Service access and Kerberoasting, recorded on the domain controller |

The gating-subcategory column is the point. Community reference works such as Randy Franklin Smith's *Windows Security Log Encyclopedia* index every event by exactly this subcategory relationship [@rfs-encyclopedia], and Microsoft's own page for 4688 states its subcategory outright: Audit Process Creation [@ms-event-4688]. The two Kerberos events live on the domain controller, under Account Logon -- the category that records authentication at the validating authority [@ms-basic-account-logon]. The mechanics of the [AS-REQ and TGS-REQ exchange](/blog/kerberos-in-windows-the-other-half-of-ntlmless/) are covered in the companion Kerberos article; here they matter only as "the DC-side record that a ticket was requested."

<Mermaid caption="The two-switch gate: an audit record exists only if the subcategory is enabled and, for object access, a matching SACL ACE is present. Miss either switch and the SRM generates nothing.">
flowchart TD
    Op["A process starts, a logon happens, or an object is accessed"] --> SRM["Security Reference Monitor evaluates the operation"]
    SRM --> G1&#123;"Is the gating subcategory enabled?"&#125;
    G1 -->|No| Drop["No event is generated"]
    G1 -->|Yes| G2&#123;"Object access needs a matching SACL ACE"&#125;
    G2 -->|No match| Drop
    G2 -->|Match, or not object access| Prov["Microsoft-Windows-Security-Auditing provider"]
    Prov --> Log["Security.evtx"]
</Mermaid>

For object-access events like 4698, that diagram hides the single most common support case in Windows auditing: two independent switches must both be set. The subcategory is the policy-level gate; the SACL ACE is the object-level match. Set one without the other and you get silence.

<RunnableCode lang="js" title="Why 'I set a SACL and saw nothing' happens">{`
// An object-access record is emitted only when BOTH switches are set.
function emitted(aceMatches, subcategoryEnabled) {
  return aceMatches && subcategoryEnabled;
}

const cases = [
  [false, false], // nothing set
  [true,  false], // SACL placed, subcategory off  -> the classic silent failure
  [false, true],  // subcategory on, no SACL        -> nothing to match
  [true,  true],  // both set                        -> the only case that logs
];

for (const [ace, sub] of cases) {
  console.log("ACE match:", ace, "| subcategory on:", sub, "=> logged:", emitted(ace, sub));
}
// Only the final combination prints logged: true
`}</RunnableCode>

> **Note:** Process-creation auditing that omits arguments cannot tell `powershell.exe` (benign) from `powershell.exe -enc <base64>` (very much not). The command-line field arrived in Event 4688 version 1 on Server 2012 R2 and Windows 8.1, and update KB3004375 (February 2015) backported the `ProcessCreationIncludeCmdLine_Enabled` policy to Windows 7, Server 2008 R2, and 2012 [@ms-event-4688, @kb3004375]. Enabling it is what turns 4688 from noise into one of the highest-value native events.

### Placing the SACL, end to end

The two-switch rule is where most "I enabled auditing and saw nothing" tickets are born, so it is worth showing the object-level switch concretely, not just naming it. There are three ways to place an audit ACE, and one way to read it back off disk.

**Per object, in PowerShell.** Read the descriptor with `Get-Acl -Audit`, add a typed audit rule, and write it back with `Set-Acl`. For a file or folder the rule is a `FileSystemAuditRule`; for a registry key it is a `RegistryAuditRule` [@ms-get-acl, @ms-filesystemauditrule, @ms-registryauditrule].

```powershell
# Audit successful and failed writes/deletes on a crown-jewel folder
$path = 'C:\CrownJewels'
$acl  = Get-Acl -Path $path -Audit
$rule = New-Object System.Security.AccessControl.FileSystemAuditRule(
          'Everyone', 'Write,Delete',
          'ContainerInherit,ObjectInherit', 'None', 'Success,Failure')
$acl.AddAuditRule($rule)
Set-Acl -Path $path -AclObject $acl

# Read the SACL back as SDDL to confirm the audit ACE landed
(Get-Acl -Path $path -Audit | Format-List -Property PSPath, Sddl)
```

**Host-global, with `auditpol`.** To audit a whole *type* of object without touching each one, set a global resource SACL: `auditpol /resourceSACL /set /type:File /user:Everyone /success /failure /access:FRFW`. The `/type` is `File` or `Key`, and the access mask uses the file codes `FR`, `FW`, `FA`, `FX` (or the key codes `KR`, `KW`, `KA`, `KX`); placing one requires the `Manage auditing and security log` right, `SeSecurityPrivilege` [@ms-auditpol-resourcesacl].

**In the GUI.** Every securable object exposes the same list under Properties, Security, Advanced, Auditing. Active Directory objects are audited the same way -- you "set a SACL on an Active Directory object by using the Security tab in that object's Properties dialog box" [@ms-basic-ds-access].

**On disk, it is just SDDL.** Whichever tool you use, the SACL is serialized as the `S:` section of the object's Security Descriptor Definition Language string, where audit entries carry the ACE type `AU` [@ms-acl-sacl]. Reading the SDDL back is the fastest way to confirm an audit ACE is actually present.

And then the second switch, which no amount of ACE placement can substitute for: a file SACL emits nothing unless *Object Access, Audit File System* is enabled, and a registry SACL needs *Audit Registry* [@ms-adv-audit-settings]. Place the ACE *and* name the subcategory -- both, or silence.

<Sidenote>SACL placement in one breath: per object, `Get-Acl -Audit` then a `FileSystemAuditRule` or `RegistryAuditRule` then `Set-Acl` [@ms-get-acl, @ms-filesystemauditrule, @ms-registryauditrule]; host-global, `auditpol /resourceSACL /set /type:File` or `/type:Key` [@ms-auditpol-resourcesacl]; by hand, the Auditing tab; on disk, the SDDL `S:` section with `AU` ACEs [@ms-acl-sacl].</Sidenote>

One more piece of literacy: mixed-era estates and old detection rules still speak in the pre-Vista 5xx numbering. The Vista rebuild renumbered events by a rough **+4096** heuristic, but the heuristic has documented exceptions, and one of them is the most important event in this article.

| Legacy ID (pre-Vista) | Current ID | Event | How it maps |
|---|---|---|---|
| 528 / 540 | 4624 | Successful logon | 528 plus 4096, with network-logon 540 folded in [@ms-appendix-l, @rfs-encyclopedia] |
| 628 | 4724 | Account password reset | The +4096 heuristic [@ms-appendix-l] |
| 610 | 4706 | New domain trust | The +4096 heuristic [@ms-appendix-l] |
| 612 | 4719 | System audit policy changed | Exception to +4096 [@ms-appendix-l] |
| 517 | 1102 | The audit log was cleared | Exception to +4096 [@ms-appendix-l] |

<Sidenote>The +4096 rule is only a heuristic. The log-cleared event became 1102, not 517 plus 4096. Microsoft publishes the authoritative legacy-to-current mapping as "Appendix L: Events to Monitor," which lists 4624 against its legacy 528 and 540 in the Low-criticality section [@ms-appendix-l]; the community encyclopedia corroborates the same mapping [@rfs-encyclopedia].</Sidenote>

<Sidenote>PowerShell script-block logging (Event 4104) and module logging (4103) land in different channels depending on the host: Windows PowerShell 5.1 versus PowerShell 7 log to distinct operational channels, so keep them straight when hunting [@ms-about-logging].</Sidenote>

Notice what every row assumes. These events exist only if policy wrote them, and they help an investigator only if they survived long enough to be read. An event correctly written to `Security.evtx` on a host the attacker owns is one `wevtutil cl security` away from gone. Which raises the question the industry keeps mis-answering: how does the log actually reach the SIEM, and can it get there before someone deletes it?

## 6. Do Not Protect the Log. Move It.

Here is the move that beats every on-host anti-forensic technique at once, and it sounds backwards: do not try to protect the log on the box. Get it off the box. The moment a copy of an event lives on a separate machine, clearing the local `Security.evtx` is no longer a way to destroy evidence -- it is only a way to announce that you tried.

Windows has shipped the machinery for this since Vista and Server 2008, agentlessly and for free.

<Definition term="Windows Event Forwarding (WEF)">
The native mechanism by which a Windows host forwards selected events to a collector over WinRM, with no third-party agent installed. Hosts are pointed at a collector and push their chosen events, or a collector pulls from a named list of sources [@ms-wef-source-init].
</Definition>

<Definition term="Windows Event Collector (Wecsvc)">
The service, driven by the `wecutil` utility, that defines subscriptions and receives forwarded events. It "enables you to create and manage subscriptions to events that are forwarded from remote computers," which "must support the WS-Management protocol" [@ms-wecutil].
</Definition>

Transport is WinRM (HTTP 5985 or HTTPS 5986), authenticated with Kerberos [@ms-winrm]. There are two subscription models, and the difference decides how the design scales.

<Mermaid caption="The two WEF subscription models over WinRM and Kerberos: source-initiated push, where hosts find the collector via Group Policy, and collector-initiated pull, where the collector holds an explicit source list.">
sequenceDiagram
    participant H as Source host
    participant GPO as Group Policy
    participant WEC as Collector Wecsvc
    Note over H,GPO: Source-initiated push mode
    GPO->>H: SubscriptionManager points host at the collector
    H->>WEC: WinRM over Kerberos, host pushes chosen events
    WEC->>WEC: Store in ForwardedEvents, update bookmark and heartbeat
    Note over WEC,H: Collector-initiated pull mode
    WEC->>H: Collector reads from an explicit source list
    H-->>WEC: Host returns events, needs Event Log Readers rights
</Mermaid>

In **source-initiated** mode, the collector defines a subscription without naming any sources; hosts are told where to report by the `SubscriptionManager` Group Policy setting and push to it [@ms-wef-source-init]. The collector holds no per-source list, so configuration scales to the whole fleet from one place. In **collector-initiated** mode, the collector holds an explicit list and pulls from each host, which must grant read access, typically via the Event Log Readers group.

Forwarded records land in the collector's `ForwardedEvents` channel, and delivery is tunable through `wecutil`: the Normal, Minimize-Latency, and Minimize-Bandwidth profiles set the delivery mode, batch size, heartbeat interval, and maximum latency behind the switches `/dm`, `/dmi`, `/hi`, and `/dmlt` [@ms-wecutil].

<Sidenote>Standing up source-initiated WEF is mostly plumbing: run `winrm qc` on the collector, push the `SubscriptionManager` GPO, and grant the Network Service account read access to the Security log so it can forward it. Deployments usually fail in that plumbing, not in the concept [@ms-wef-source-init, @jepayne-wef].</Sidenote>

<Sidenote>WEF scales by how you store what the collector receives: Microsoft's guidance routes 0 to 5,000 events per second to a SQL or SEM (Security Event Manager, the era's term for what is now a SIEM) backend, 5,000 to 50,000 to a SEM, and 50,000 or more to Hadoop, HDInsight, or a data lake, with MapReduce ingress measured in hundreds of terabytes per day [@ms-wef-intrusion]. Note the trade buried in the delivery profiles: Minimize-Bandwidth deliberately *defers* forwarding to batch it, which widens the window between a local write and its off-box copy [@ms-wecutil].</Sidenote>

WEF is a deliberately **passive** system. Microsoft is explicit: it "can't change the size of event log files, enable disabled event channels, change channel permissions, or adjust a security audit policy. WEF only queries event channels for existing events" [@ms-wef-intrusion]. It forwards only what audit policy already wrote, and only while the Event Log service is still recording. That constraint matters later: WEF cannot resurrect an event a never-enabled subcategory failed to produce.

In 2015, Jessica Payne of Microsoft reframed this obscure plumbing as a first-class security control for anyone, SIEM or not. Her argument is compact: WEF is free and built-in, configured through Group Policy, uses Windows Remote Management with Kerberos to resist man-in-the-middle interference, and -- the load-bearing point -- it gets the evidence off the host before anyone can tamper with it [@jepayne-wef].

<PullQuote>
"'Push' log mode -- less attack surface than adding a monitoring agent or account to a widely privileged group." -- Jessica Payne, on why WEF is a security control, not just plumbing [@jepayne-wef]
</PullQuote>

<Aside label="From obscure plumbing to blue-team doctrine">
Payne's 2015 talk and post, and the companion WEFFLES threat-hunting console she published, turned a shipped-since-2008 feature into standard blue-team practice [@jepayne-wef, @weffles]. The technology did not change. The framing did: forwarding stopped being about convenience and started being about durability.
</Aside>

There is a second, quieter gift in the design. The collector keeps a per-source **bookmark** and **last-heartbeat time**; an idle source still sends periodic heartbeats to signal it is alive [@ms-wef-intrusion]. That heartbeat is what converts a silenced host from an *absence of events* -- which looks exactly like a quiet night -- into a *detectable silence*: the collector notices the beat stopped.

> **Note:** You cannot make a local log tamper-proof against someone who owns the machine. But you can make tampering pointless and loud. Off-box forwarding relocates the authoritative copy, so clearing the local log (Event ID 1102) arrives too late, and the missing heartbeat turns even a perfectly silent host into an alert. This one control survives clearing, disabling, and thread-termination alike [@ms-wef-intrusion].

Off-box durability changes the adversary's problem from "delete the evidence" to "delete the evidence everywhere, before it ships, without going quiet." But most organizations never read `ForwardedEvents` directly. They pay a SIEM to read it for them. So what, precisely, does that SIEM ingest?

## 7. What the SIEM Actually Ingests

"What your SIEM actually sees" is not a promise. It is a configuration file, and there is one on every hop.

For Microsoft Sentinel, the modern path is the **Azure Monitor Agent** governed by **Data Collection Rules**. You deploy the agent to each host -- Azure-native, or Arc-connected for on-premises and hybrid -- and attach one or more rules that decide which Security events are collected and where they land, namely the `SecurityEvent` and `WindowsEvent` tables [@ms-sentinel-connectors, @ms-ama-overview].<MarginNote>`SecurityEvent` is the curated Windows-security table most detections query; `WindowsEvent` is the more generic landing table. A DCR can route to either, so knowing which one your rules read is part of knowing what the SIEM sees.</MarginNote>

<Definition term="Data Collection Rule (DCR)">
The cloud-authored rule that tells the Azure Monitor Agent what to collect, how to process it, and where to send it. Critically, a DCR can "apply a transformation to filter or modify incoming data before it's sent to a destination" [@ms-dcr-overview] -- so the DCR is the ETL filter that decides which events survive ingestion.
</Definition>

That filtering power is also a hazard: a DCR tuned too tightly is a silent-drop point above a host that logged and even forwarded correctly. The predecessor agent is already gone -- the Log Analytics agent, also called MMA or OMS, was retired on 31 August 2024 [@ms-ama-migration, @azure-mma-retire], with its cloud ingestion able to stop after 2 March 2026 [@ms-ama-migration]. AMA plus DCRs is the mandated replacement.

Splunk's path is parallel. The Universal Forwarder reads the Security channel through the `[WinEventLog://Security]` input in `inputs.conf`, filtering by `EventCode` whitelist or blacklist [@splunk-wineventlog]. It can read a host directly, or it can be pointed at a WEF collector's `ForwardedEvents` channel -- which means WEF from the previous section composes *beneath* the forwarder rather than competing with it. One hardened collector, one forwarder reading it.

| Method | Transport and auth | Filter locus (silent-drop risk) | Cloud/hybrid fit | Off-box value |
|---|---|---|---|---|
| WEF source-initiated | WinRM / Kerberos | Subscription XML query | On-prem, per-estate | High |
| WEF collector-initiated | WinRM / Kerberos | Subscription XML query | On-prem, per-estate | High |
| AMA + DCR to Sentinel | HTTPS to Azure (Arc for hybrid) | DCR transform | Native via Arc | High, cloud copy |
| Splunk UF `[WinEventLog://Security]` | Splunk to indexers | `EventCode` whitelist/blacklist | Good | High, indexer copy |

Across all four methods, one constraint now dominates the design: money. Azure Monitor Logs bills for the volume you ingest per gigabyte, and Microsoft calls ingestion and retention "the most significant charges for most Azure Monitor implementations" [@ms-cost-logs]. Splunk's license economics push the same way. So teams filter hard at the DCR or the input stanza -- which quietly revives the coarse era's dilemma one layer up. Where the 1990s admin turned auditing down to save disk and performance, the 2020s engineer filters ingestion to save budget, and both can drop the one event that mattered.

<Sidenote>The collection surface is itself a moving target: the Azure portal for Microsoft Sentinel is announced to consolidate into the unified Microsoft Defender portal by 2027 [@ms-sentinel-connectors]. A working pipeline can break on a platform migration nobody scheduled around.</Sidenote>

> **Note:** This is the boundary of the native pipeline. Once the event lands in `SecurityEvent` or a Splunk index, the work of detection begins -- [KQL analytics, correlation rules, and incident triage](/blog/one-event-three-portals-how-a-single-sysmon-line-becomes-a-m/). That analytics layer belongs to the companion article on the SOC dashboard. Here we care only about whether the event reaches the table at all, because everything downstream is blind to an event that never arrived.

Stack the filters and the thesis becomes arithmetic. Audit policy decides what is written. The SACL decides whether object access is written. The WEF subscription decides what forwards. The DCR or `EventCode` list decides what ingests. Each layer is a valve, and every valve can silently shut on the event you needed. Not one of them lives in the SIEM.

There is one more source of confusion to clear before we turn to the attacker, because a lot of teams believe they have already solved this problem with a different tool. "We run Sysmon," they say, "so we do not need the Security log." Both halves of that sentence misread the stack.

## 8. One Producer Among Several

Take the claim apart. "We run Sysmon, so we do not need the Security log" assumes [Sysmon](/blog/from-cmdexe-to-a-kusto-row-in-90-seconds-how-sysmon-and-defe/) is a replacement for native auditing. It is not. And the flip side -- "the Security log is separate from Sysmon and EDR, a different kind of thing" -- is also wrong, because at the plumbing level they are the same kind of thing. Both halves of the myth dissolve once you separate four axes: who *produces* the telemetry, which *channel* it lands in, what *configuration surface* controls it, and what *detection intent* it serves.

<Definition term="Event Tracing for Windows (ETW)">
The high-speed, general-purpose tracing facility built into Windows since Windows 2000. The Windows Event Log, including the Security channel, is delivered over ETW's unified provider model [@park-buch-etw]. So "the Security log" is not a peer of ETW -- it is one consumer riding on it.
</Definition>

| Axis | Native Security audit (this article) | Sysmon | MDE / EDR |
|---|---|---|---|
| Producer | `Microsoft-Windows-Security-Auditing` via LSASS and the SRM | A separately installed driver and service | Kernel callbacks plus `EtwTi` |
| Channel | `Security.evtx`, the 46xx event IDs | `Microsoft-Windows-Sysmon/Operational` | Cloud `Device*` tables |
| Config surface | GPO, `auditpol`, CSV, and SACLs | An XML configuration file | Cloud policy |
| Detection intent | Policy and accountability logging | High-fidelity endpoint telemetry | Behavioral cloud detection |
| Relationship | The layer the others quietly assume | Parallel, not a successor | A different substrate entirely |

Read down the columns and the myth collapses in both directions. Sysmon is a *different producer* writing to a *different channel* with a *different configuration surface* -- so it cannot be a drop-in replacement for the accountability record that regulators, incident responders, and domain-controller forensics all expect in `Security.evtx`. But it is also not architecturally separate: Sysmon, EDR, and native audit all ride the ETW-based Windows plumbing [@park-buch-etw]. The honest framing the whole article rests on is that native audit is a *different producer, channel, configuration surface, and detection intent* on the same substrate -- not a separate universe.

<Aside label="Differentiate, do not duplicate">
This article owns exactly one column of that table: the native Security-audit configuration surface -- audit policy, SACLs, and forwarding -- that decides what `Security.evtx` contains before any agent reads it. ETW internals (providers, sessions, buffers) belong to the ETW article; Sysmon's event catalogue and Defender for Endpoint's on-host architecture belong to the Sysmon and MDE article; the `Device*` Advanced Hunting tables and incident correlation belong to the SOC-dashboard article. The point of naming them here is to place the native subsystem among its neighbors, not to re-explain them.
</Aside>

> **Note:** The Security log rides ETW just as Sysmon and EDR do. What makes it distinct is not the transport -- it is the intent. Native audit is policy-driven accountability logging: it records what your configured audit policy says to record, in a schema built for attribution, on a channel that predates the SIEM and outlives any one vendor. Confusing "same plumbing" with "same thing" is how teams end up with three overlapping tools and one un-configured foundation [@park-buch-etw].

So the native Security log is one deliberately configured producer among several. That word -- *configured* -- is the whole vulnerability. Sysmon can be uninstalled and EDR can be tampered with, but native auditing is uniquely exposed because it is assembled from a dozen independent switches that ship, by default, mostly off. Anything you configure, an adversary can misconfigure for you, or silence outright. So flip sides: what does an attacker who now owns the box turn off, and in what order?

## 9. What Attackers Silence, and in What Order

You own the box. The SIEM is watching. You want the log to go dark without tripping an alert. The techniques form a ladder, and each rung exists to erase the tell the rung below it leaves. All three sit under MITRE ATT&CK's parent technique **T1685, "Disable or Modify Tools,"** in the tactic **TA0112, "Defense Impairment"** -- the tactic for actions that "degrade, disable, or undermine the effectiveness and trustworthiness of security controls and monitoring mechanisms" [@mitre-t1685, @mitre-ta0112].

**A1, clear the whole log.** With administrator rights, `wevtutil cl security`, `Remove-EventLog -LogName Security`, or direct deletion of the `.evtx` files under `C:\Windows\System32\winevt\logs` wipes the local trail in one stroke. This is **T1685.005, "Clear Windows Event Logs"** -- the technique formerly tracked as T1070.001, whose page now meta-refreshes to the current ID [@mitre-t1685-005, @mitre-t1070-001-deprecated]. It is also the loudest option. Clearing the Security log itself emits **Event ID 1102**, "the audit log was cleared" [@ms-appendix-l], a single high-signal event every SIEM alerts on. And if WEF already forwarded those records, the off-box copy survives untouched. Destructive, noisy, and often too late.

**A2, disable or suppress before the write.** Quieter attackers turn the tap off upstream: `auditpol /clear /y` to wipe policy; `Set-Service -Name EventLog -Status Stopped` (or `Stop-Service`) to stop the running service immediately, while `sc config eventlog start=disabled` only sets its startup type to Disabled, which keeps it from restarting at the next boot but leaves the running service alive until a manual stop; or -- notably possible *without* administrator privileges -- setting the Autologger key `HKLM\SYSTEM\CurrentControlSet\Control\WMI\Autologger\EventLog-Security` `Start` value to 0 so the Security trace session never starts at the next boot.

This is **T1685.001, "Disable or Modify Windows Event Log"** (formerly T1562.002) [@mitre-t1685-001]. No 1102, because nothing is cleared. But it still leaves tells: a stopped or disabled service is directly observable, an `auditpol` change can emit Event ID 4719, and a reboot-persistent Autologger edit is catchable by configuration baselining.

**A3, terminate the log threads and leave the service "Running."** The current apex of stealth exploits an implementation detail: the Event Log service runs as threads inside a shared `svchost.exe`.<MarginNote>Windows co-hosts many services inside shared `svchost.exe` processes to save resources, which is exactly why terminating one service's threads can leave the enclosing process, and its reported service state, looking perfectly healthy.</MarginNote> A tool like Phant0m locates that service and terminates only its worker threads, leaving the service object intact [@phant0m].

<PullQuote>
"While the Event Log service appears to be running in the system... it does not actually run... and the system does not collect logs." -- the Phant0m project, describing thread-termination suppression [@phant0m]
</PullQuote>

The result defeats the naive health check outright: no 1102, no stopped-service state, no 4719. `services.msc` shows EventLog "Running." Here is that false comfort in code.

<RunnableCode lang="js" title="The health check Phant0m defeats">{`
// A naive monitor trusts the service state alone.
const eventLog = { serviceState: "Running", threadsAlive: false };

function naiveHealthy(s) {
  return s.serviceState === "Running";                    // what most checks test
}
function trulyHealthy(s) {
  return s.serviceState === "Running" && s.threadsAlive;  // what is actually required
}

console.log("Naive check says healthy:", naiveHealthy(eventLog)); // true  -> false comfort
console.log("Actually recording      :", trulyHealthy(eventLog)); // false -> silenced
`}</RunnableCode>

<Mermaid caption="Where each rung of the adversary ladder hits the pipeline. Clearing erases the local copy after the write; disabling and thread-termination block the write. Only the off-box collector, and its heartbeat, survives all three.">
flowchart LR
    subgraph HOST["On the compromised host"]
      W["Event in Security.evtx"]
      A1["A1 clear log, emits 1102"]
      A2["A2 disable service or policy"]
      A3["A3 Phant0m terminates the log threads"]
    end
    subgraph OFF["Off the box, out of reach"]
      WEC["Collector holds the forwarded copy"]
      HB["Missing heartbeat becomes a signal"]
    end
    W --> WEC
    WEC --> HB
    A1 -.->|clears after write| W
    A2 -.->|blocks the write| W
    A3 -.->|blocks the write| W
</Mermaid>

| Technique | ID | Pre or post write | Primary tell it leaves | Beaten by |
|---|---|---|---|---|
| Clear the log | T1685.005 | Post-write | Event ID 1102; the off-box copy survives | Off-box WEF |
| Disable or suppress | T1685.001 | Pre-write | Service state, possible 4719, config drift | Config baselining plus WEF heartbeat |
| Phant0m thread-termination | T1685.001 | Pre-write | Only the silence itself | The collector noticing the silence |

This ladder, and the broader family of event-pipeline tampering, was systematized in Palantir's 2018 study, which MITRE cites on the parent technique [@palantir-etw-tamper, @mitre-t1685]. And it is precisely here that many teams reach for the wrong shield.

<Definition term="Protected Event Logging">
A Windows 10 feature that lets participating applications encrypt sensitive data written to the event log, using the IETF Cryptographic Message Syntax and public-key cryptography, so that a captured script block does not hand an attacker plaintext credentials [@ms-about-logging]. It is a *confidentiality* control for log contents.
</Definition>

> **Note:** Protected Event Logging encrypts what a log entry says. It does not stop an attacker from clearing the log (A1), disabling the service (A2), or terminating its threads (A3). Presenting it as a tamper or integrity defense is a common and dangerous misreading. The real integrity control against this ladder is off-box forwarding plus a hardened, append-only collector [@ms-about-logging].

Every rung erases the previous rung's tell -- except one signal it cannot reach. The off-box collector still notices that the host went quiet, because the heartbeat stopped. Which forces the honest question that governs the rest of this article: even configured perfectly and forwarded instantly, what can this subsystem *never* see?

## 10. Auditing Is Observation, Not Enforcement

Suppose you win. Every useful subcategory is enabled, the crown-jewel objects carry precise SACLs, the force setting is confirmed, and a hardened collector drains every host in near real time. There is still a floor beneath which this subsystem cannot see, and it is worth stating precisely, because it is the formal version of the thesis.

The SIEM's ground truth is not "what happened on the host." It is an intersection of three independently fallible sets.

$$ \text{SIEM ground truth} \;=\; \mathrm{written}(A) \,\cap\, \mathrm{survived}(C) \,\cap\, \mathrm{shipped}(B) $$

Only what audit policy wrote (layer A), only what survived the attacker (layer C), and only what forwarding shipped (layer B). If policy never wrote an event -- no enabled subcategory, or a SACL with no gating subcategory -- then no collector can recover it. Microsoft says as much of WEF: it is passive and "only queries event channels for existing events" [@ms-wef-intrusion]. The ceiling on detection is set at layer A, beneath the SIEM's line of sight.

> **Key idea:** The SIEM does not see reality. It sees an intersection: what was written, what survived, and what shipped. Every term in that intersection is a configuration decision made below the dashboard -- so the detection ceiling is set by the audit policy and forwarding config, not by the analytics on top of them.

Three hard limits live inside that intersection.

**Some actions are SACL-silent by construction.** You cannot place an audit ACE on an access that never happens. Directory-replication attacks such as [DCSync and DCShadow](/blog/two-checkmarks-and-the-keys-to-the-kingdom-how-active-direct/) abuse the replication protocol rather than opening an audited object: DCSync reads secrets over it [@mitre-t1003-006], while DCShadow injects attacker-controlled changes through it from a rogue domain controller [@mitre-t1207]. Because neither touches an audited file, key, or object, no SACL placement closes the gap -- a *different* sensor, such as domain-controller directory-service auditing, is required to see them at all.

<Sidenote>DCSync and DCShadow are the canonical SACL-silent operations: DCSync reads secrets and DCShadow injects changes, but both abuse replication rather than opening a file or key, so object auditing sees nothing. They are covered in the companion article on directory replication attacks; here they stand for a whole class of behavior that native object auditing structurally cannot observe.</Sidenote>

**There is a provable window between write and forward.** WEF is asynchronous and batched. The `wecutil` delivery profiles tune that window -- Minimize-Latency shrinks it, Minimize-Bandwidth deliberately widens it, and `/dmlt` sets it explicitly [@ms-wecutil] -- but they never drive it to zero. So a window in which an event is written locally but not yet shipped provably exists. Near-real-time streaming narrows it; nothing native eliminates it.

**The local log has no native tamper-evidence.** A `.evtx` file carries no cryptographic chaining and no signature, and a SYSTEM- or kernel-privileged adversary owns the host. Local integrity therefore cannot be guaranteed against such an adversary; forwarding does not make the *local* copy tamper-proof, it merely relocates the *authoritative* one. That is the honest statement of what off-box collection buys and what it does not.

The gap is not a mystery of computer science. Tamper-evident logging is a solved problem. In 1999, Bruce Schneier and John Kelsey published a construction for **forward-secure, hash-chained** audit logs, in which each entry authenticates its predecessor and the signing key evolves through a one-way function -- so that an attacker who compromises the host at time *T* cannot undetectably alter any entry written before *T*, even knowing the current key [@schneier-kelsey-1999]. The mathematics has existed for a quarter century. Native Windows implements none of it on the live `Security.evtx`. Protected Event Logging supplies confidentiality, not this integrity [@ms-about-logging].

> **Note:** An audit trail records that something happened. It does not prevent it, and it does not defend itself. Native Windows auditing is observation, and the observer lives on the very host the adversary compromises. That is why durability is an operational property -- get the record off-box fast, to an append-only store -- and not a cryptographic one.

There is thus a real, measurable distance between what is provably achievable -- forward-secure, tamper-evident logging -- and what Windows natively provides, which is none of it. That distance is exactly where the field's open problems live.

## 11. Where the Foundation Is Still Soft

These open problems are not academic curiosities. Each one is a concrete reason your next breach might be invisible on a fully deployed SIEM.

**Native tamper-evidence at the source.** The live `Security.evtx` still has no forward-secure integrity, so a host-privileged adversary can clear, suppress, or terminate its threads and the *local* record cannot prove it was altered. The cryptographic construction that would fix this has existed since 1999 [@schneier-kelsey-1999], and as Section 10 established, Protected Event Logging deliberately does not attempt it. The best available answer remains operational: forward off-box to an append-only, immutable collector. Strong, but not source-cryptographic.

**Closing the async gap.** To defeat a perfect act-then-silence race, an audit record would have to be durably off-box *before* the audited operation's effect is durable. Minimize-Latency delivery and a small `/dmlt` shrink the window toward the transport round-trip [@ms-wecutil], and near-real-time streaming narrows it further, but synchronous pre-effect commit at fleet scale trades directly against host performance and remains impractical. The window shrinks; it does not close.

**Detecting suppression reliably.** Because a thread-termination tool defeats the "is the service running?" check, the only durable signal is the *absence* of expected events -- the WEC per-source heartbeat and bookmark make that silence visible [@ms-wef-intrusion]. Turning "unexpected silence" into a timely, low-false-positive alert, across hosts with wildly different normal activity, is an unsolved engineering problem, not a solved product feature.

**Log everything, or log what matters, under real budgets.** The ingestion-cost dilemma from Section 7 is itself an open problem: because every SIEM bills by volume, cost, not disk, now drives filtering. The current best answer is a *prioritized* baseline rather than a maximal one.

<Aside label="Log what matters, multinationally">
The tension now has an explicit, multinational answer. The Australian Signals Directorate's ACSC, with CISA, the FBI, the NSA, and international partners, published "Best Practices for Event Logging and Threat Detection," which explicitly balances coverage against resourcing constraints [@cisa-logging-2024]. It is the policy-level resolution of the tension that has run through this entire subsystem: not "audit everything," not "audit nothing," but "audit what matters, and be able to afford it."
</Aside>

**Platform churn as a hazard in its own right.** The collection surface keeps moving underneath working pipelines. The Log Analytics agent was retired on 31 August 2024, with ingestion able to stop after 2 March 2026 [@ms-ama-migration], and the Sentinel Azure portal is consolidating into the unified Defender portal [@ms-sentinel-connectors]. Each migration is an opportunity for a correctly designed pipeline to silently stop delivering.

> **Note:** None of these platform shifts throws an error in your dashboard. An estate that forwarded flawlessly on the old agent can simply stop populating a table after a deadline nobody tracked. Treat every mandated migration as a detection outage until you have re-verified an end-to-end test event landing in the SIEM.

Each of these marks a place where the foundation is still soft -- where the honest answer is "we manage the risk operationally," not "we have solved it." Which brings us back to the only question that matters once the theory is on the table: on Monday morning, with the tools that actually ship, what do you do?

## 12. The Checklist That Turns the Board Red Before the Breach

Everything so far was diagnosis. Here is the treatment -- the sequence that would have caught our opening post-mortem while there was still a log to catch it in. Work top to bottom; each step assumes the one above it.

1. **Confirm the force setting, and verify *effective* policy.** Assume `SCENoApplyLegacyAuditPolicy` is on. Then run `auditpol /get /category:*` on the host and read what is actually in effect -- not the GPO you believe you set [@ms-auditpol, @ms-force-setting].
2. **Deploy a subcategory baseline, not a basic one.** Start from Microsoft's System Audit Policy recommendations and the 2024 multinational logging guidance, then tune to your threat model [@ms-audit-recommendations, @cisa-logging-2024].
3. **Turn on Process Creation with the command line, and PowerShell script-block logging.** A 4688 without arguments is nearly blind; script-block logging (Event 4104) captures what ran [@ms-event-4688, @ms-about-logging].
4. **Place targeted SACLs on crown-jewel objects -- and remember the second switch.** Use `Get-Acl -Audit` with a `FileSystemAuditRule` or `RegistryAuditRule` and `Set-Acl`, or `auditpol /resourceSACL`, or the Auditing tab -- then confirm the gating Object Access subcategory is enabled, because the ACE does nothing without it [@ms-get-acl, @ms-filesystemauditrule, @ms-auditpol-resourcesacl, @ms-acl-sacl].
5. **Forward off-box.** Stand up a source-initiated WEF collector and forward `ForwardedEvents` to the SIEM, so clearing a local log is too late [@ms-wef-source-init, @jepayne-wef].
6. **Alert on the tells, and on silence.** Fire on Event ID 1102 (log cleared) and 4719 (audit policy changed), and monitor WEC heartbeats for hosts that go quiet -- the one signal that beats a thread-termination tool [@ms-wef-intrusion].
7. **Harden the collector.** Make it append-only or immutable; an unprotected collector is a single point of failure that erases your off-box guarantee.
8. **Do not lean on Protected Event Logging for tamper resistance.** It is confidentiality only [@ms-about-logging].

Step 2 hides a decision most teams make by accident: *which* baseline. The frameworks genuinely disagree, and the disagreement lands squarely on Object Access. Microsoft's own Security Compliance baseline leaves Object Access with no recommendation at all -- it is "intended only to be a starting baseline guide," and each organization must decide for itself [@ms-audit-recommendations].

The DoD STIG for Windows Server 2022 (V2R8) goes the other way: it mandates Object Access subcategories at Success *and* Failure where Microsoft is silent, and it requires the force setting itself, rule WN22-SO-000050 [@dod-stig-ws2022]. CIS agrees with the stricter posture -- its Windows Server 2022 Benchmark v2.0.0 sets Audit Removable Storage to "Success and Failure" [@cis-benchmark-ws2022]. That single Object Access decision is the difference between a quiet log and a much larger, costlier one.

> **Note:** Microsoft SCM, CIS, and the DoD STIG do not agree on Object Access auditing: SCM recommends nothing there [@ms-audit-recommendations], while CIS and the STIG push subcategories such as Removable Storage to Success and Failure [@cis-benchmark-ws2022, @dod-stig-ws2022]. That is materially more log volume and cost. Pick a framework deliberately and know why -- do not inherit the divergence by accident.

A defensible starting set for step 2 looks like this -- adjust volumes to your estate, and note the column where the frameworks part ways.

| Subcategory | A defensible setting | Baseline stance (SCM / CIS / STIG) | What it catches |
|---|---|---|---|
| Process Creation (with command line) | Success | Broadly recommended | Execution and encoded commands (4688) |
| Logon | Success and Failure | Broadly agreed | Lateral movement and spraying (4624, 4625) |
| Special Logon | Success | Broadly agreed | Privileged sessions (4672) |
| User Account Management | Success and Failure | Broadly agreed | Rogue account creation (4720) |
| Audit Policy Change | Success and Failure | Broadly agreed | Policy tampering (4719) |
| Removable Storage (Object Access) | Success and Failure | SCM: none; CIS and STIG: Success and Failure | Device-based exfiltration and use |
| Other Object Access Events | Success | SCM: none; STIG: Success and Failure | Scheduled-task persistence (4698) |

> **Note:** Run `auditpol /get /category:*` on a sample of hosts and confirm they are auditing what you assume. Enable command-line process auditing. Stand up one WEF collector and forward to your SIEM. Those three moves turn the largest blind spots visible, and none of them requires new licensing [@ms-auditpol, @ms-event-4688, @jepayne-wef].

<Spoiler kind="solution" label="Verify your effective audit policy right now">
Open an elevated prompt and run `auditpol /get /category:*`. Every subcategory reports one of "No Auditing," "Success," "Failure," or "Success and Failure." If a category you configured through basic Group Policy shows "No Auditing," you have just watched the force setting override your legacy toggle in real time [@ms-auditpol, @ms-force-setting]. Fix it at the subcategory level, re-run, and confirm the change before you trust it.
</Spoiler>

> **Key idea:** Return to the green dashboard. The subcategory that was never enabled, the SACL that was never set, the log that was cleared, and the Event Log threads that were quietly killed -- every one of those failures lived beneath the SIEM's line of sight, in the audit policy and forwarding config the dashboard silently assumed. That is the thesis, now with evidence: your SIEM is only as good as the audit policy and forwarding beneath it, and the attacker went straight for the foundation.

Every step above is work you do below the dashboard. That is not a coincidence. It is the entire lesson: the board turns red before the breach only if the plumbing beneath it was built to make it.

## 13. Misconceptions, Cleared Up

<FAQ title="Frequently asked questions">
<FAQItem question="If I turn on Object Access auditing, does it audit everything?">
No. The Object Access subcategory is only the gate. To record access to a specific file, key, or directory you also need a SACL -- an audit ACE -- on that object. Place it with `Get-Acl -Audit` and `Set-Acl`, or with `auditpol /resourceSACL`, then enable the gating subcategory. Both switches must be set, or you get silence [@ms-acl-sacl, @ms-auditpol-resourcesacl].
</FAQItem>
<FAQItem question="Can I just configure both basic and advanced audit policy?">
Not safely. On a modern host the default-on force setting makes the advanced subcategory surface win, so basic toggles are ignored, and Microsoft warns that mixing the two "can cause unexpected results." Pick advanced policy and force it [@ms-force-setting, @ms-adv-audit-faq].
</FAQItem>
<FAQItem question="Does Protected Event Logging protect my logs from tampering?">
No. It is a confidentiality control: it encrypts sensitive log *contents* with CMS and public-key cryptography so a captured script block does not leak credentials. It does not stop clearing, disabling, or thread-termination [@ms-about-logging].
</FAQItem>
<FAQItem question="Isn't the log-clearing technique T1070.001?">
That ID is deprecated. It now redirects to T1685.005, "Clear Windows Event Logs," under parent technique T1685 and the tactic TA0112, "Defense Impairment." Cite the current IDs; treat T1070.001 only as a legacy alias [@mitre-t1685-005, @mitre-t1070-001-deprecated].
</FAQItem>
<FAQItem question="Is the Security log separate from ETW?">
No. The Windows Event Log, Security channel included, is delivered over Event Tracing for Windows. Native audit is not architecturally separate from ETW; it is a different producer, channel, and detection intent riding the same plumbing [@park-buch-etw].
</FAQItem>
<FAQItem question="Does Sysmon replace the Security log?">
No. Sysmon is a different producer writing a different channel with a different configuration surface and intent. It is a parallel telemetry source, not a successor to native accountability logging -- and it cannot supply the `Security.evtx` records forensics and compliance expect [@park-buch-etw].
</FAQItem>
<FAQItem question="If an attacker clears the local log, is the evidence gone?">
Not if Windows Event Forwarding already shipped it. Clearing emits Event ID 1102 and the off-box collector still holds the forwarded records, which is exactly why getting logs off the box is treated as a security control [@jepayne-wef, @mitre-t1685-005].
</FAQItem>
</FAQ>

The dashboard at the top of your SOC is the most visible thing you own and the least load-bearing. Everything it can ever show was decided by cheaper machinery underneath it: which subcategory was enabled, whether an object carried a SACL, whether the record left the box before someone deleted it. Attackers learned this before most defenders did, which is why they aim at the audit policy and the forwarding config, not the console.

The practical consequence is almost unfair in its simplicity: spend your next hardening hour beneath the dashboard, on the layer nobody demos, because that is the layer that decides whether the demo is telling the truth.

<StudyGuide slug="beneath-the-dashboard-windows-security-log" keyTerms={[
  { term: "SACL", definition: "The audit half of a security descriptor: a list of audit ACEs that make the system generate records in the Security log." },
  { term: "Advanced Audit Policy subcategory", definition: "One of the fine-grained audit switches that superseded the coarse basic categories, tunable to Success, Failure, both, or neither." },
  { term: "Force setting (SCENoApplyLegacyAuditPolicy)", definition: "The default-on flag that makes subcategory policy override the legacy basic categories, so basic toggles silently no-op." },
  { term: "Windows Event Forwarding (WEF)", definition: "Native, agentless forwarding of selected events to an off-box collector over WinRM and Kerberos." },
  { term: "Data Collection Rule (DCR)", definition: "The cloud-authored ETL filter that decides which events the Azure Monitor Agent ingests into Microsoft Sentinel." },
  { term: "Event ID 1102", definition: "The record that the Security audit log was cleared; MITRE ATT&CK technique T1685.005." },
  { term: "Phant0m", definition: "A tool that terminates the Event Log service threads so the service shows Running while recording nothing; MITRE ATT&CK T1685.001." }
]} questions={[
  { q: "Why can a basic Object Access toggle audit nothing on a modern host?", a: "The default-on force setting makes the subcategory surface authoritative, so the legacy category toggle is ignored." },
  { q: "What two switches must both be set for an object-access event to fire?", a: "The gating Object Access subcategory and a matching SACL audit ACE on the object." },
  { q: "Why is off-box forwarding the one control that survives clearing, disabling, and thread-termination?", a: "It relocates the authoritative copy and converts a silenced host into a detectable missing heartbeat at the collector." }
]} />
