Security Operations

What Is a SIEM?

HuntRule Team · · 8 min read

A dense industrial pipe manifold at night where dozens of intake lines converge into a single gauge-covered junction
On this page

Sysmon Event ID 1 carries a field called CommandLine. By the time a detection queries that value in Splunk it is Processes.process, in Elastic it is process.command_line, and in Microsoft Sentinel's ASIM it is TargetProcessCommandLine. Same bytes, four names, and every rename is a place a rule can stop matching without anyone noticing.

That is the honest description of a SIEM. It is a log pipeline with a query engine and a scheduler bolted on. The query engine is the part vendors demo. The pipeline is the part that decides whether your detections work.

The data path

Everything a SIEM does happens in this order:

  1. Collection. An agent, a syslog listener or an API poller pulls raw events.

  2. Parsing. Raw text or XML becomes structured key/value pairs.

  3. Normalisation. Vendor field names are mapped onto a common schema.

  4. Enrichment. Asset, identity and threat intel lookups add context.

  5. Storage. Events land in a tier, then age into cheaper tiers.

  6. Search and correlation. Ad hoc queries plus scheduled rules that fire alerts.

Steps 5 and 6 are the product. Steps 1 through 4 are where detection engineering actually lives.

Collection decides what exists

A detection cannot match a field that was never collected. The classic example is Windows Security event 4688, "A new process has been created". By default 4688 records NewProcessName and ProcessId but no command line at all. The command line only appears after you enable the Audit Process Creation policy setting:

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Audit
  ProcessCreationIncludeCmdLine_Enabled (DWORD) = 1

Without that value, every rule keyed on a command-line string silently returns zero across your entire Windows estate. The pipeline is healthy. The dashboard is green. The field is empty.

4688 also has no parent command line, ever. Sysmon Event ID 1 does, under ParentCommandLine. Two sources that both claim to be "process creation" telemetry, with different ceilings on what you can detect.

Parsing breaks quietly

Parsers fail loudly when a format changes shape and silently when a format changes meaning. CEF is the usual offender. The header is fixed, but the custom string slots are label-driven:

CEF:0|Vendor|Firewall|9.1|100|Traffic denied|5|src=10.0.0.5 dst=203.0.113.9 spt=51314 dpt=443 act=blocked cs1Label=RuleName cs1=Block-Egress

A vendor upgrade moves the rule name from cs1 to cs2 and puts a policy ID in cs1. Your parser still reads cs1 into rule_name. Nothing errors. The field now contains a policy ID, and every correlation that groups by rule name starts producing garbage buckets. We have seen this class of break survive for weeks because the only symptom is an alert that stopped firing.

The detection engineering fix is a canary: a scheduled search that counts events where the normalised field is null over a window it should never be null in. That is cheap and almost nobody has one.

Normalisation loses fields

Normalisation maps vendor fields onto a common schema so a rule can be written once. The cost is that the schema is a lossy projection. Anything the schema does not model does not survive.

Microsoft's ASIM Process Event schema is a clean example. It defines ParentProcessName, ParentProcessId, ParentProcessGuid and a dozen other parent attributes. It does not define a parent command line field at all. The closest thing is ActingProcessCommandLine, which describes the process that performed the action rather than the process tree parent. For process creation those are usually the same, and "usually" is doing real work in that sentence. A Sigma rule written against ParentCommandLine has no clean target in ASIM.

That is one field in one schema. Multiply it across every source you onboard.

Rows of sealed storage crates receding into freezing fog, one crate lit from within

Storage tiering makes retro-hunts theoretical

Every SIEM ages data into cheaper storage. Splunk moves index buckets from hot to warm to cold to frozen, and frozen is deleted unless you configured an archive. Elasticsearch runs content, hot, warm, cold and frozen tiers, where cold holds fully mounted searchable snapshots and frozen holds partially mounted ones backed by object storage. Azure Monitor and Microsoft Sentinel do it with table plans instead of nodes: Analytics, Basic and Auxiliary.

The Sentinel numbers are worth stating precisely. Analytics retention is 90 days for Microsoft Sentinel, extendable to two years at a long-term retention charge, and total retention reaches 12 years across all three plans. So "we keep a year of logs" is true. What Microsoft also documents is that on the Auxiliary plan, KQL is limited to a single table, there is no restore, and the plan is not optimised for real-time analysis.

Read that back against a real retro-hunt. You get a new IOC and want to know whether that domain was resolved anywhere in the last twelve months. The data is retained. The join across DNS, proxy and process tables that would answer the question is not available in the tier holding eleven of those months. Technically possible, operationally impossible, and the difference never shows up on a retention report.

Licensing decides your telemetry

Most SIEM pricing is a function of gigabytes ingested per day. That makes the cheapest way to cut cost the removal of high-volume, low-signal-density sources. In practice that is DNS query logs, proxy logs, and endpoint telemetry beyond process creation.

Those are exactly the sources retro-hunts and C2 detections need. A team optimising the invoice and a team optimising detection coverage are pulling the same lever in opposite directions, and the invoice usually wins because it has a number attached and coverage does not.

The same detection, two schemas

Take a certutil download, T1105 Ingress Tool Transfer, often paired with T1140 for the decode step. The logic is one line: a process named certutil.exe whose command line contains both urlcache and http.

Splunk, against the accelerated CIM Endpoint data model:

| tstats summariesonly=t count min(_time) as firstTime max(_time) as lastTime
    FROM datamodel=Endpoint.Processes
    WHERE Processes.process_name=certutil.exe
      AND Processes.process="*urlcache*"
      AND Processes.process="*http*"
    BY Processes.dest Processes.user Processes.parent_process_name Processes.process
| rename "Processes.*" as "*"

Elastic, in Kibana Query Language against ECS:

event.category:process and event.type:start
  and process.name:"certutil.exe"
  and process.command_line:*urlcache*
  and process.command_line:*http*

Note what changed and what did not. The logic is identical. The field names share nothing. And CIM's naming is an outright trap: Processes.process is the full command line, while Processes.process_name is only the leaf file name. A rule author who maps CommandLine to Processes.process_name gets a syntactically valid search that matches nothing.

Here is the mapping cost written out, from Sysmon's native names across three schemas:

Sysmon

Splunk CIM (Endpoint.Processes)

ECS

ASIM ProcessEvent

Image

Processes.process_path

process.executable

TargetProcessName

(leaf name only)

Processes.process_name

process.name

TargetProcessFilename

CommandLine

Processes.process

process.command_line

TargetProcessCommandLine

ParentImage

Processes.parent_process_path

process.parent.executable

ActingProcessName

ParentCommandLine

Processes.parent_process

process.parent.command_line

ActingProcessCommandLine

OriginalFileName

Processes.original_file_name

process.pe.original_file_name

TargetProcessFileOriginalName

User

Processes.user

user.name

TargetUsername

Computer

Processes.dest

host.name

DvcHostname

That table is the answer to "are Sigma rules portable". They are portable exactly as far as the schema is, and a backend that cannot resolve a field to a real column produces a rule that runs and never fires. This is the mechanical reason Sigma ships pipelines separately from rules.

What the rule catches and misses

Catches: certutil invoked with -urlcache and an HTTP or HTTPS URL, which is the standard download-a-payload pattern.

Misses, and these matter:

  • Renamed binaries. Matching on process_name fails against cu.exe. Add original_file_name=CertUtil.exe to close it, which requires Sysmon or an EDR that populates the PE original name. 4688 does not.

  • Hosts where ProcessCreationIncludeCmdLine_Enabled is not set. No command line, no match, no error.

  • certutil -verifyctl -f -split and other download-capable flags that never contain the string urlcache.

  • Data model acceleration gaps. summariesonly=t reads only accelerated summaries. If acceleration has not backfilled the searched window, the tstats returns fewer rows than the raw index holds.

Known false positives: administrators and deployment scripts using certutil to fetch CRLs or installers, and vendor software that calls it during update. Baseline by parent process before enabling. Note that certutil -urlcache * delete, the common cache-clearing command, does not match here because it contains no http.

More Windows process-creation logic is in the catalog at /rules?domain=windows.

What a SIEM does not do

A SIEM does not decide what to collect. It will accept whatever you point at it, tier it correctly, retain it for twelve years and never once ask whether a single rule reads it. Storage is not coverage. The decision about which telemetry earns its ingest cost is a detection engineering decision made outside the tool, and it is the highest-leverage decision in the whole stack.

Summary

A SIEM is collection, parsing, normalisation, enrichment, storage and query, in that order. Detections break in the first four steps and get debugged in the last one, which is why they take so long to find. Schema choice determines rule portability, and a lossy schema like ASIM's missing parent command line puts a hard ceiling on what a ported rule can express. Tiering and ingest-based licensing then quietly decide which hunts are affordable, long before anyone writes a query.

Fields worth confirming exist before you trust any process-creation rule:

process command line     Sysmon EID 1 CommandLine
                         4688 requires ProcessCreationIncludeCmdLine_Enabled=1
parent command line      Sysmon EID 1 ParentCommandLine (absent from 4688 and ASIM)
pe original file name    Sysmon EID 1 OriginalFileName (defeats renamed LOLBins)
process integrity level  Sysmon EID 1 IntegrityLevel
logon session id         4688 SubjectLogonId (joins process to authentication)

Related articles