Detection Engineering

What Is Security Telemetry?

HuntRule Team · · 9 min read

A single instrument probe on a taut tether descending into a deep dark shaft, its cable running up out of frame
On this page

Sysmon Event ID 3, network connection, is disabled by default. Microsoft says so in the Sysmon documentation, right above the note that it links every connection to a process through ProcessId and ProcessGuid. Leave the default and no rule on your estate can tie an outbound session to the binary that opened it.

Nobody there decided against detecting C2 egress. Someone accepted a default, or trimmed a config to cut volume, and the detection became impossible three quarters later. That is telemetry: the raw material of detection, and where your ceiling gets set before a single rule is written. Every rule you cannot write is a telemetry decision someone made earlier, usually on cost grounds.

Endpoint

Process events are the backbone. Sysmon Event ID 1 carries Image, CommandLine, ParentImage, ParentCommandLine and Hashes. Windows Security 4688 carries the new process name but no parent command line, ever. The parent chain is what turns a benign binary into a detection. winword.exe spawning cmd.exe is the entire signal, and 4688 cannot express it.

File events come from Sysmon Event ID 11 with TargetFilename. Pair it with a web root path and webshell drops (T1505.003) become a file artifact rather than a guess. Registry events come from Sysmon 12, 13 and 14, or Windows Security 4657. A rule keyed on TargetObject ending in \CurrentVersion\Run\<name> catches T1547.001 at write time instead of at next boot.

Process access is Event ID 10, the only endpoint source that sees one process reading another's memory. That is credential dumping (T1003.001) without knowing the tool.

<Sysmon schemaversion="4.82">
  <EventFiltering>
    <RuleGroup groupRelation="or">
      <NetworkConnect onmatch="exclude" />
    </RuleGroup>
    <RuleGroup groupRelation="or">
      <ProcessAccess onmatch="include">
        <TargetImage condition="image">lsass.exe</TargetImage>
      </ProcessAccess>
    </RuleGroup>
  </EventFiltering>
</Sysmon>

The first group turns Event ID 3 on for everything. The second turns Event ID 10 on only for LSASS, because unfiltered ProcessAccess is one of the loudest events Sysmon makes.

Identity

Active Directory gives you 4624 with LogonType (3 network, 9 NewCredentials, 10 RemoteInteractive), 4625 for failures, 4768 and 4769 for Kerberos ticket requests, and 4776 for NTLM validation. 4769 with TicketEncryptionType of 0x17 is RC4-HMAC, the Kerberoasting signal (T1558.003) on a domain that has otherwise moved to AES.

DCSync (T1003.006) is visible in 4662, but only if you have earned it. The event needs Audit Directory Service Access enabled and a SACL on the domain naming context. Then you match the replication extended rights:

1131f6aa-9c07-11d1-f79f-00c04fc2dcd2   DS-Replication-Get-Changes
1131f6ad-9c07-11d1-f79f-00c04fc2dcd2   DS-Replication-Get-Changes-All

Most estates have neither the audit subcategory nor the SACL. The rule exists in every public catalog and fires nowhere.

In Entra ID the equivalent tables are SigninLogs and AADNonInteractiveUserSignInLogs. Password spraying (T1110.003) shows up as many distinct UserPrincipalName values against one IPAddress with ResultType 50126. Collect only SigninLogs and you miss token refreshes, because they land in the non-interactive table.

Network

Zeek is the reference implementation here because its output is already fields rather than packets. A conn.log line:

{"ts":1591367999.430166,"uid":"C5bLoe2Mvxqhawzqqd","id.orig_h":"192.168.4.76","id.orig_p":46378,"id.resp_h":"31.3.245.133","id.resp_p":80,"proto":"tcp","service":"http","duration":0.25411510467529297,"orig_bytes":77,"resp_bytes":295,"conn_state":"SF","history":"ShADadFf","orig_pkts":6,"resp_pkts":4}

duration, orig_bytes and resp_bytes grouped by id.orig_h and id.resp_h over a day is a beaconing hunt. You want low variance in interval and near-constant byte counts, which is what a fixed-sleep implant produces before jitter is tuned.

dns.log gives you query and answers. Long labels, high subdomain cardinality under one registered domain and a TXT-heavy qtype_name distribution is DNS tunneling (T1071.004). ssl.log gives you server_name, the SNI, which survives TLS and is often the only name you get for an encrypted session.

NetFlow and IPFIX give you the five-tuple, byte and packet counts and TCP flags. Enough for beaconing and volumetric exfil. Not enough for SNI, DNS queries or URIs, so a NetFlow-only shop finds the rhythm of a C2 channel but not its destination.

Cloud control plane

Cloud audit logs record API calls, not host behaviour. In AWS that is CloudTrail, and the split that matters is management events against data events. Management events cover the control plane. CreateAccessKey where the calling userIdentity is not the target user is an attacker minting a second credential (T1098.001). StopLogging, DeleteTrail and PutEventSelectors are the log tampering that precedes everything else. CloudTrail Event history holds 90 days of management events in a Region for free, which is a retro-hunt window that costs nothing.

Data events cover the objects. AWS documents it plainly: trails and event data stores do not log data events by default, and additional charges apply. S3 GetObject is a data event. So is Lambda Invoke. Bulk read of a bucket is invisible on a default trail, and no rule fixes that.

Application

Web server access logs give you method, path, status, bytes and user agent. A POST to a .aspx path with no prior GET traffic is a webshell (T1505.003), and the access log alone will not tell you the file is new. Join it to Sysmon Event ID 11 on the same path and the detection has two independent confirmations. If an app authenticates locally rather than through the IdP, its own login events are the only identity telemetry for that surface.

The four things that decide whether a source is usable

Completeness across the estate. A rule covering the 70 percent of endpoints with a healthy agent looks identical, in the console, to a rule covering everything. The failure is silent and it inverts a quiet dashboard. Absence of evidence gets read as evidence of absence.

Field fidelity. The field is present and its value is wrong for your purpose. Firewall logs record post-NAT source addresses, so every internal host collapses into one gateway IP. Web servers behind a load balancer log the balancer unless something parses X-Forwarded-For. The rule matches. The entity it names is not the entity that acted.

Latency. AWS documents CloudTrail as delivering logs within an average of about five minutes of an API call, and states the time is not guaranteed. Fine for detecting persistence. Not fine for blocking a key created, used and deleted inside three.

Retention. Entra ID Free keeps audit and sign-in logs for seven days. P1 and P2 keep 30. Threat intel routinely arrives 60 days after the activity, and a retro-hunt against it returns nothing. Nothing is indistinguishable from clean.

An industrial sorting chute where a narrow lit lane carries a thin stream of ore while a wide dark chute swallows the bulk

The cost conversation, which is the real constraint

Ingest pricing shapes what gets collected. Arguing that everything should be collected is not a plan, because the budget was set by someone who has never read a Sigma rule.

The framing that survives that meeting is collection tiers. High-value telemetry goes hot: indexed, searchable in seconds, available to scheduled rules. That is process creation, process access on LSASS, registry writes to autorun locations, authentication events, cloud management events and DNS queries. Low volume relative to their value, and they carry the fields rules key on.

Bulk telemetry goes cold: object storage, cheap per gigabyte, queried on demand. Full proxy logs, NetFlow, raw web access logs, DHCP, S3 data events. You do not run scheduled rules against cold storage. You go there once an alert or an intel report gives you a pivot.

Be honest about what cold costs. Query latency moves from seconds to minutes, and some architectures charge per scan. Calling a source "collected" when it is cold is how coverage maps stop matching reality.

Work backwards from the technique to the field

This is the exercise that tells you whether you can detect something at all.

  1. Name the behaviour, not the tool. "A process opens LSASS and reads its memory", not "Mimikatz".

  2. Name the observable. A handle open on lsass.exe with PROCESS_VM_READ in the access mask.

  3. Name the source and the exact field. Sysmon Event ID 10, TargetImage and GrantedAccess.

  4. Check the source is on. Is ProcessAccess in your Sysmon config, and is LSASS included rather than excluded?

  5. Check the field survives the pipeline. Does GrantedAccess reach your SIEM, and does normalisation keep it?

Only after step 5 do you write the rule. Steps 1 to 3 take minutes. Steps 4 and 5 are where most techniques die.

title: LSASS memory access with read rights
status: experimental
description: Detects a process opening lsass.exe with an access mask that permits reading its memory
logsource:
    category: process_access
    product: windows
detection:
    selection:
        TargetImage|endswith: '\lsass.exe'
        GrantedAccess:
            - '0x1038'
            - '0x1438'
            - '0x143a'
            - '0x1fffff'
    filter_optional_agents:
        SourceImage|startswith:
            - 'C:\Program Files\'
            - 'C:\Program Files (x86)\'
    condition: selection and not 1 of filter_optional_*
falsepositives:
    - EDR, antivirus and backup agents that read process memory
    - Performance monitoring and crash reporting tools
level: medium

What it catches: a process opening LSASS with a mask including PROCESS_VM_READ (0x0010), the minimum needed to read credentials out of memory.

What it misses: GrantedAccess is a bitmask, so an enumerated list of values is brittle by construction. A tool requesting an unusual combination produces a mask not on the list and walks past. Handle duplication and driver-based reads do not produce Event ID 10 at all. If ProcessAccess is filtered out of your Sysmon config the rule is inert and still looks healthy.

False positives are constant, because security agents read LSASS legitimately. The Program Files filter is a weak start, since an attacker who writes to a subdirectory there inherits the exclusion. Tighten it to specific signed image paths.

Summary

Telemetry is the constraint layer under every detection programme. Endpoint, identity, network, cloud control plane and application each expose a small number of fields that real detections key on. Completeness, fidelity, latency and retention decide whether a source you have is a source you can use. Cost is the real limit, so run collection tiers and accept that cold telemetry cannot carry a real-time rule. To learn whether a technique is detectable, work backwards from the behaviour to the exact field.

Technique

Source

Field

T1003.001 LSASS Memory

Sysmon Event ID 10

TargetImage, GrantedAccess

T1003.006 DCSync

Windows Security 4662

Properties (replication GUIDs)

T1547.001 Registry Run Keys / Startup Folder

Sysmon Event ID 13

TargetObject, Details

T1558.003 Kerberoasting

Windows Security 4769

TicketEncryptionType, ServiceName

T1110.003 Password Spraying

Entra SigninLogs

ResultType, IPAddress, UserPrincipalName

T1071.004 Application Layer Protocol: DNS

Zeek dns.log, Sysmon Event ID 22

query, QueryName

T1098.001 Additional Cloud Credentials

AWS CloudTrail

eventName, userIdentity.arn

T1505.003 Web Shell

Web access log, Sysmon Event ID 11

uri, TargetFilename

Minimum hot-tier collection to make that table workable:

Sysmon         1, 3, 7, 10, 11, 12, 13, 22
Windows        4624, 4625, 4657, 4662, 4688, 4769, 4776
Entra ID       SigninLogs, AADNonInteractiveUserSignInLogs, AuditLogs
AWS            CloudTrail management events (all Regions)
Zeek           conn.log, dns.log, ssl.log, http.log
Application    web server access logs, application auth logs

Once the fields are arriving, the rules are the easy part. Browse the endpoint rules at /rules?domain=windows, or search a source you just turned on with /rules?q=lsass. If you are earlier than that, start with what detection engineering is.

Related articles