How do you prove an emulated technique's miss was absent auditd telemetry, not an unmatched rule?
answer
- empty SIEM has three explanations
- look on the host first
- control host proves the record exists
- widen the window for clock skew
- absent at source versus lost in transit
basics
~20 sSearch the host's own audit log over the known window, against a positive-control host that does produce the record. No record on the host is a collection gap; a record present clears collection and moves the test to the rule.
solid answer
~50 sYou have ground truth — host, command, timestamp — so make the search unmissable: the exact window, the host, the process. Look in the **host's own audit log first**, because an empty SIEM search has three explanations (never recorded, recorded but never delivered, delivered but normalised into a shape your search does not hit) and only the first is a rule-loading problem. Run the same technique on a **positive-control host** where the `execve` audit rule is loaded: if the record appears there and not on the target, you have localised the gap to that host class and proved your harness worked. Check clock skew before concluding a window was empty. If the record does exist, the collection link is fine and you move on to re-running the rule's own query over it. Remediating the audit configuration is the telemetry owner's job, not yours; your job is the attribution.
code
text · 7 linestype=SYSCALL msg=audit(1751293841.372:88214): arch=c000003e syscall=59
success=yes exit=0 ppid=1 pid=20871 auid=4294967295 uid=0 gid=0 euid=0
tty=(none) ses=4294967295 comm="collect.sh" exe="/usr/bin/bash"
key="exec" ...
type=EXECVE msg=audit(1751293841.372:88214): argc=2 a0="/usr/bin/bash"
a1="/opt/svc/collect.sh"
type=PROCTITLE msg=audit(1751293841.372:88214): proctitle=...go deeper
Know that an empty search result is not the same as an event never happening, and that the host's own log is the place to settle it.
Be ready to list the three reasons a platform search comes back empty — never recorded, never delivered, delivered in a shape the query misses — and how you tell them apart.
Show that you always run a positive control and widen for clock skew, so your negative finding survives being challenged by the team it lands on.
Set the evidence bar for the programme: no exercise finding is accepted as a collection gap without a control-host artefact and a scope statement about the host class.
## What you are trying to distinguish Two findings look identical from the pager and cost completely different things to fix: - **The event never existed.** Nothing on that host wrote a record of the behaviour. No query, however good, could have matched. - **The event existed and nothing matched it.** The estate recorded the behaviour and had no rule that said anything about it. You executed the technique, so you know the ground truth: which host, which command line, which second. That turns the question into an evidence exercise rather than a guess. ## Start at the host, not the platform The instinctive move — search the SIEM over the execution window and find nothing — is the move that produces the wrong answer, because an empty result there has at least three causes: 1. The record was never generated (the `execve` audit rule was not loaded, or auditd was not running). 2. The record was generated and never delivered (agent stopped, filter dropped it, queue backed up). 3. The record was generated and delivered, but normalisation renamed or dropped the field your search keyed on, so it is sitting there under a different shape. Only (1) is truly "absent telemetry at the source"; (2) is a delivery problem and (3) is not a telemetry problem at all. So look on the host itself over the window and see whether the local audit log holds the syscall record for your execution. Then compare with what the platform holds for the same window. Host-yes/platform-no is a pipeline finding. Host-no is a collection finding at the source. ## The positive control The single most persuasive artefact in this whole exercise is a **control host**: a machine of a different build class, known to have the `execve` rule loaded, on which you run the identical command. If the record appears there and is absent on the target, you have simultaneously proved three things — the technique does emit an auditable record, your harness actually ran, and the difference is the host's own configuration. Without a control, "I found nothing" is not distinguishable from "I searched badly". The same logic covers your persistence step. A systemd timer's unit file lands on disk; a file-write watch would record the write, and the journal separately records the unit starting. Where auditd is silent but the journal shows the unit being started, the behaviour was observable on a *different* surface — which changes the finding from "invisible" to "visible somewhere nobody is looking", and that is a materially different recommendation. ## Traps that produce a false "absent" - **Clock skew.** Your harness timestamp and the host's clock may differ by minutes. Widen the window generously before declaring emptiness; a five-minute search around a skewed clock manufactures collection gaps that do not exist. - **Searching by the wrong identifier.** For a timer-launched process there is no login session: the audit record carries an unset `auid` and `ses`. A search filtered by a user identity will legitimately return nothing for a record that is right there. - **Truncated fields.** The `comm` field is a short process name, not the command line; the argument vector lives in the `EXECVE` record. Searching `comm` for a script path finds nothing even though the record exists. - **Retention.** If you look a week later and the raw index has aged out, absence is meaningless. Do this walk-back within the retention of the source you are searching. ## Writing the conclusion If the host never wrote the record, the finding is a **collection gap on a named host class**, and it is scoped: state how you know it is the class and not just the one machine you tested. If the record was there all along, you have exonerated collection and the next step is to run the rule's own logic over the stored record — where a non-match has its own two explanations, real logic gap versus a normalisation mismatch that stripped the field the rule keys on. One boundary worth stating out loud in an interview: your output is the attribution and its evidence. *Loading the audit rule across the image class* belongs to whoever owns that image and its telemetry, and *rewriting the rule* belongs to the detection engineers. Purple team's product is the proof of which of them is on the hook.
- The platform holds no record but the host's own audit log has it. Which link is that, and who owns it?Collection, but the delivery half of it rather than the source: the behaviour was recorded and never arrived. The owner is whoever runs the shipping path — agent health, filters, queueing — not the detection team. The distinction matters because the fix is delivery, and a rule written in the meantime still cannot fire.
- The record is in the platform but the rule's query returns nothing when re-run. What are the two explanations?Either the rule's logic genuinely does not describe the behaviour, or normalisation dropped or renamed the field the rule keys on, so a sound rule is reading a shape that no longer exists. Test by matching against the raw record and the normalised one separately; only the first case is a detection-logic gap.
- Why is a positive-control host worth the extra run?It separates "the record does not exist" from "I searched badly". A control of a build class known to carry the execve audit rule, running the identical command, should produce the record. If it does, your harness worked and the record type is real, so absence on the target is a property of the target. Without it your finding rests on a negative you cannot defend.
- Why can a search filtered on the invoking user return nothing for a timer-launched process?A process started by a systemd timer has no login session behind it, so the audit record carries an unset loginuid and session identifier rather than a user. Filtering on identity excludes exactly the record you are looking for, and the analyst concludes there is a collection gap that does not exist.
saying these in an interview costs you the question
- Treats an empty SIEM search as proof nothing was recorded
- Never checks the host's own audit log
- Runs no control host, so the negative is undefendable
- Ignores clock skew and searches a five-minute window
- Confuses the short comm field with the command line