Security Engineering
Designing CTI → SOC Detection Pipelines
The last mile is where most threat intelligence value dies. Turning an assessment into a detection converts something probabilistic and time-bound into something deterministic and permanent — and almost nothing in the usual design notices the conversion.
- detection engineering
- SOC
- detection lifecycle
- ATT&CK
- feedback loops
A threat intelligence function can do everything upstream correctly — characterise its sources, preserve provenance, grade evidence, state confidence — and still deliver nothing, because the last mile was treated as a data-transfer problem rather than a design problem.
The last mile is the conversion of an assessment into a control. It is the only point at which intelligence changes anyone’s behaviour, and it is routinely the least engineered part of the whole chain.
The conversion nobody models
An assessment and a detection are different kinds of object, and the difference is not cosmetic.
| Intelligence assessment | Detection rule | |
|---|---|---|
| Truth value | Probabilistic — likely, moderate confidence | Binary — matched or did not |
| Lifespan | Explicitly time-bound; decays | Runs until someone deletes it |
| Basis | Evidence, with sources and grades | Logic, with no memory of why |
| Owner | Analyst who signed it | Whoever is on call tonight |
| Revision | Revisited when evidence changes | Revisited when it becomes annoying |
Writing a detection performs a type conversion across every row of that table at once. The confidence is dropped, because the rule has nowhere to put it. The expiry is dropped, because rule formats have no expiry field. The evidential basis is dropped, because the rule carries logic, not reasoning.
A detection is an assessment frozen into code — and it outlives the assessment that justified it, because only one of the two has an expiry date.
Six months later the rule is still running. The infrastructure it matched has been reassigned. The analyst who wrote it has moved on. The reasoning exists, if anywhere, in a ticket nobody will find. And the alert it produces at 03:00 looks identical to the one it produced when it was correct.
This is not a tooling gap that a better SIEM fixes. It is a modelling gap: the pipeline was designed to move intelligence to the SOC, and the thing it actually has to do is translate it — which means deciding, explicitly, what happens to the properties that do not survive translation.
The wrong default: new intelligence means a new rule
Most CTI → SOC pipelines have one verb. Intelligence arrives, a detection is written. The volume of intelligence is large, so the volume of detections grows, and nothing removes any.
The result is detection debt, and it behaves exactly like technical debt with one difference: the interest is not paid by the team that incurred it. It is paid by an analyst, at night, triaging an alert whose justification expired eleven months ago.
Three defaults are better, and the choice between them should be explicit for every piece of intelligence that arrives.
Enrich, don’t alert. The highest-yield and most under-used option. Attach the intelligence as context to events that are already being surfaced: this address appeared in reporting on campaign X six weeks ago, source graded C3. It costs nothing in false positives, it improves every triage decision it touches, and it degrades gracefully — stale enrichment is merely unhelpful, whereas a stale rule is actively harmful.
Hunt, don’t alert. Some intelligence is worth a question rather than a control: did this behaviour occur in our estate in the last ninety days? Retrospective hunting is where decayed indicators still have real value, because the question is historical and decay does not apply to it.
Alert — but only when you can answer the third question. Which brings us to the gate that should sit in front of every detection.
Three questions before any detection ships
1. What behaviour does this detect? Not “what artefact does it match” — what behaviour. If the answer is only an artefact, the detection sits at the bottom of the Pyramid of Pain and will die when the adversary recompiles. That may still be worth shipping, but it changes the retirement policy, which is question four’s problem.
2. What does a benign instance of this look like? If nobody can describe one, the rule has not been thought through — every detection worth having matches something legitimate occasionally, and the person who cannot name that something has not looked for it. This question, asked honestly, kills more bad rules than any amount of tuning after deployment.
3. What does the analyst do when it fires? The gate. A detection with no defined response is not a detection; it is a notification. Notifications with no action attached are ignored, then muted, then deleted — and the muting happens quietly, so the dashboard continues to report the rule as active long after anyone stopped reading its output.
If question three has no answer, the intelligence should have been enrichment.
What has to travel with a detection
The properties lost in translation have to be carried explicitly, as metadata, because the rule logic cannot hold them. At minimum:
intel_ref— the specific intelligence product that motivated this, not a feed name. Without it, the rule’s justification is unrecoverable the moment its author leaves.confidence— the assessed confidence of the underlying judgement, carried forward rather than silently promoted to certainty by the act of writing a rule.pyramid_tier— hash, address, domain, artefact, tool, or behaviour. This is the single best predictor of how long the rule will remain valid, so it should drive the review interval rather than a uniform one.review_by— a date. A rule with no review date is permanent by default, and permanence was never assessed.expected_benign— the answer to question two, written down, so the next person to tune it does not have to rediscover it.response— the answer to question three, or a link to it.last_validated— the date this rule was last shown to fire on a known positive.
That last field is the one I would add first if I could only add one, for reasons that take a section of their own.
Two failure directions that look identical
A detection can fail in two opposite ways, and on a dashboard they produce the same picture.
Too broad. It fires constantly on benign activity. The analysts learn to dismiss it, then to filter it, then to disable it. The failure is loud at first and then goes silent — and the silence is the dangerous part, because the rule is still listed as covering the technique.
Too narrow. It never fires. Perhaps nothing matched it; perhaps it is broken — the field name changed in a log source upgrade, the index it queries stopped being populated, the logic never worked at all. It reports healthy because it produces no errors.
Both end at the same observation: a rule that is not firing. And the two readings of that observation are opposite. One means “excellent precision, nothing to see”. The other means “this control has not existed for four months”.
Nothing in a rule’s own telemetry distinguishes them. The only thing that does is an external test: feed it a known positive and confirm it fires.
A detection never observed to fire is indistinguishable from one that does not work. Until you have made it fire on demand, its contribution to your coverage is unknown — not low, unknown.
This is cheap. A known-positive test per rule, run on a schedule, with the date recorded. It converts “we have 400 detections” — a claim about rules written — into “we have 340 detections demonstrated to fire within the last quarter”, which is a claim about capability.
Coverage maps are a trap
The ATT&CK heat map is the standard artefact for showing detection coverage, and in its usual form it measures the wrong thing.
A technique is marked covered because a rule exists that references it. The map does not know whether the rule works, whether it has ever fired, whether the log source it depends on is still being ingested, or whether the technique has a dozen variants of which the rule catches one.
So the map reports rules written, displayed under a label that reads as attacks detected. Green spreads across the board while capability does not follow.
Three corrections, in order of how much they change the picture:
- Colour by last-validated date, not by rule existence. A technique whose rule has not been demonstrated to fire this quarter is not green. It is unknown, and it should have its own colour — distinct from both covered and uncovered, because “we have not tested” is a different statement from “we do not cover”.
- Record the log sources each rule depends on, and monitor those separately. The most common way a detection dies is that its input stops arriving. The rule is fine. It is querying an empty table.
- Record which variant of a technique is covered. Sub-technique granularity, or a written note. A single rule against one variant marks the whole technique green and leaves the rest of it unexamined.
The feedback loop is the actual product
Most CTI → SOC pipelines run in one direction. Intelligence flows down; nothing flows back. That is the largest structural waste in the arrangement, because the SOC is continuously generating intelligence about the intelligence, and almost nobody collects it.
What the SOC knows that CTI does not:
- Which products led to a detection that fired on something real.
- Which fired constantly on benign activity — a direct measure of a source’s precision.
- Which indicators were already stale on arrival.
- Which alerts were muted, and when, and by whom.
- Which techniques analysts keep encountering that no product ever covered.
Route that back and the collection programme becomes steerable. Without it, the CTI function’s only available metrics are volume metrics — products issued, indicators ingested — which measure effort and are compatible with producing no effect at all.
The minimum viable loop is not elaborate: every detection references its intel_ref, and
every alert disposition is recorded against that reference. That alone lets you answer did
this intelligence product change anything?, which almost no function can currently answer
about its last fifty products.
Reverse the direction
The strongest version of this pipeline runs the other way round, and it is a change of posture rather than of architecture.
Instead of intelligence arrives → what can we detect with it, start from here is what we need to detect → collect against that. The detection engineers state their requirements; those requirements become the collection plan.
This is what Priority Intelligence Requirements are for, and it is the step most commonly skipped — with a predictable consequence. Without stated requirements, relevance has no criterion, so collection expands to fill the budget and the function’s only defensible metric becomes how much it collected.
A useful requirement is specific enough to be refuted: “we need to know which credential access techniques are being used against organisations in our sector, and which of them leave artefacts in the log sources we actually ingest.” That second clause is what makes it a detection requirement rather than a reading list.
A diagnostic
Run this against your own environment. The answers are cheap to get, which is unusual for architectural questions, and the gaps tend to rank themselves.
- What fraction of production detections carry a reference to the intelligence that motivated them?
- What is the median age of detections, and how many have ever been reviewed?
- How many have been demonstrated to fire on a known positive, and when?
- How many depend on a log source that is no longer being ingested?
- Which detections fired in the last quarter, and what proportion of those firings led to any action?
- Which muted or disabled rules are still counted as coverage?
- Can you name one collection decision that was changed by SOC feedback in the last six months?
Question six is usually the most uncomfortable and the fastest to fix. Question seven is the one that says whether this is a pipeline or a chute.
The design in one paragraph
Treat the CTI → SOC boundary as a translation with known losses, and carry the lost properties explicitly: confidence, expiry, and the reason. Default to enrichment, escalate to hunting, and alert only where a response is defined. Give every detection a lifecycle with a review date and a retirement condition, and drive the interval from where the detection sits on the Pyramid of Pain. Validate that each rule can fire, on a schedule, and record the date — then colour your coverage map by that date rather than by whether a rule exists. And close the loop, because what the SOC learns about the intelligence is the only signal that tells the collection programme where to point.
The stage-by-stage view of the pipeline that feeds into this is in From OSINT Collection to Actionable Cyber Threat Intelligence; why the boundaries between those stages fail is in Why CTI Pipelines Fail at Handoffs; and what has to travel with an indicator for it to support a decision at all is in IOC ≠ Intelligence.
สรุปภาษาไทย
หน่วยข่าวกรองทำงานต้นน้ำถูกต้องครบทุกอย่างได้ — จัดชั้นแหล่งข่าว รักษาที่มา ประเมิน ความเชื่อมั่น — แล้วยัง ส่งมอบคุณค่าเป็นศูนย์ ถ้าปลายทางถูกมองว่าเป็นปัญหา การส่งข้อมูล แทนที่จะเป็นปัญหา การออกแบบ
- 🔑 การแปลงที่ไม่มีใครสร้างแบบจำลองไว้ — คำประเมินกับกฎตรวจจับเป็นวัตถุคนละชนิด คำประเมินเป็น ความน่าจะเป็น และ มีอายุ · กฎตรวจจับเป็น ไบนารี และ อยู่จนกว่าจะมีคนลบ การเขียนกฎคือการแปลงชนิดข้ามทุกแถวพร้อมกัน ⇒ ความเชื่อมั่นถูกทิ้ง (กฎไม่มีช่องให้ใส่) วันหมดอายุถูกทิ้ง (รูปแบบกฎไม่มีฟิลด์นี้) เหตุผลถูกทิ้ง (กฎถือตรรกะ ไม่ได้ถือการให้เหตุผล) 🔴 กฎตรวจจับคือคำประเมินที่ถูกแช่แข็งเป็นโค้ด — และมันอยู่นานกว่าคำประเมินที่รองรับมัน เพราะมีแค่ฝ่ายเดียวในสองฝ่ายที่มีวันหมดอายุ
- ⛔ ค่าปริยายที่ผิด: “ข่าวกรองมาใหม่ = เขียนกฎใหม่” ⇒ เกิด หนี้การตรวจจับ ซึ่งเหมือนหนี้ทางเทคนิคต่างกันข้อเดียว — คนจ่ายดอกเบี้ยไม่ใช่ทีมที่ก่อหนี้ แต่เป็นนักวิเคราะห์ที่นั่งคัดแจ้งเตือนตอนตีสาม จากเหตุผลที่หมดอายุไปแล้วสิบเอ็ดเดือน → ค่าปริยายที่ดีกว่า: ① เสริมบริบท ไม่ใช่แจ้งเตือน (ได้ผลสูงสุดและถูกใช้น้อยสุด · ข้อมูลเก่าที่เสริมบริบทแค่ ไม่มีประโยชน์ แต่กฎเก่า เป็นโทษ) ② ตั้งเป็นคำถามล่า (ตัวบ่งชี้ที่เสื่อมแล้วยังมีค่าเต็มที่กับคำถามย้อนหลัง) ③ แจ้งเตือน — เฉพาะเมื่อตอบข้อ ③ ได้
- สามคำถามก่อนปล่อยกฎ: ① ตรวจจับ พฤติกรรม อะไร (ไม่ใช่ ร่องรอย อะไร) ② ตัวอย่างที่ไม่เป็นภัยหน้าตาเป็นยังไง (ถ้าไม่มีใครบอกได้ แปลว่ายังไม่ได้คิด) ③ นักวิเคราะห์ต้องทำอะไรเมื่อมันดัง ⛔ ถ้าตอบข้อ ③ ไม่ได้ สิ่งนั้นควรเป็นการเสริมบริบท
- 🔑 ความล้มเหลวสองทิศทางที่หน้าตาเหมือนกัน — กฎที่ กว้างเกิน จะถูกปิดเสียงเงียบ ๆ · กฎที่ แคบเกินหรือพัง จะไม่ดังเลย ⇒ ทั้งคู่จบที่การสังเกตเดียวกันคือ “กฎที่ไม่ดัง” ซึ่งอ่านได้สองแบบที่ตรงข้ามกัน: “แม่นยำเยี่ยม” กับ “ด่านนี้ไม่มีอยู่จริงมาสี่เดือนแล้ว” ⛔ ไม่มีอะไรใน telemetry ของกฎแยกสองอย่างนี้ได้ · สิ่งเดียวที่แยกได้คือ ป้อนตัวอย่างที่รู้ว่าใช่ แล้วดูว่ามันดังไหม
- แผนที่ความครอบคลุม ATT&CK เป็นกับดัก — มันนับ กฎที่เขียนไว้ แล้วแสดงใต้ป้ายที่อ่านว่า การโจมตีที่ตรวจจับได้ → แก้สามข้อ: ① ระบายสีตามวันที่พิสูจน์ล่าสุด ไม่ใช่ตามการมีกฎ และ “ยังไม่ได้ทดสอบ” ต้องมีสีของตัวเอง ⛔ ไม่ใช่สีเดียวกับ “ครอบคลุมแล้ว” หรือ “ไม่ครอบคลุม” ② เฝ้าดูแหล่งข้อมูลที่กฎพึ่งพา (กฎตายบ่อยที่สุดเพราะ อินพุตหยุดมา ตัวกฎไม่ได้พัง มันแค่ query ตารางว่าง) ③ บันทึกว่าครอบคลุม variant ไหนของเทคนิค
- 🔑 วงป้อนกลับคือตัวผลผลิตจริง — SOC ผลิต ข่าวกรองเกี่ยวกับข่าวกรอง ตลอดเวลา (ผลิตภัณฑ์ไหนนำไปสู่การตรวจจับของจริง · ตัวไหนดังแต่เรื่องไม่เป็นเรื่อง · ตัวไหนเก่าตั้งแต่มาถึง · ใครปิดเสียงอะไรเมื่อไร) แต่แทบไม่มีใครเก็บกลับ ⇒ หน่วยข่าวกรองจึงเหลือแต่ตัวชี้วัดเชิงปริมาณ ซึ่ง วัดความพยายาม และเข้ากันได้ดีกับการไม่เกิดผลอะไรเลย
- กลับทิศทาง — แทนที่จะเป็น ข่าวกรองมาถึง → เอาไปตรวจจับอะไรได้บ้าง ให้เริ่มจาก เราต้องตรวจจับอะไร → เก็บข่าวสารตามนั้น นี่คือหน้าที่ของ PIR และเป็นขั้นที่ถูกข้ามบ่อยที่สุด ⇒ เมื่อไม่มีความต้องการที่ประกาศไว้ ความเกี่ยวข้องก็ไม่มีเกณฑ์ การเก็บจึงขยายไปเต็มงบ และตัวชี้วัดเดียวที่เหลือคือ เก็บได้เยอะแค่ไหน