skip to content

Attack Trees and Abuse Cases

Modelling an attacker's goal as a tree of AND/OR sub-goals, costing the cheapest path, and writing abuse cases that mirror user stories. Interviewers use it to test systematic attacker thinking.

on this pageshow

explore

questions

24

In an attack tree, how do node costs propagate through AND versus OR nodes to the root?

level: middleimportance: must knowfreq 62%

answer

  1. who gets to choose, attacker or defender
  2. conjunction versus alternative
  3. one operator adds, one selects
  4. the smallest alternative sets the parent

basics

~20 s

In an attack tree, an AND node costs the sum of its children, because the attacker must complete all of them. An OR node costs the minimum, because the attacker picks one. The root holds the cheapest complete attack.

solid answer

~50 s

Propagation is bottom-up. For a cost-like attribute, an **AND** node takes the **sum** of its children (every subgoal has to be achieved, so every cost is paid) and an **OR** node takes the **minimum** (the attacker only needs one alternative and will choose the cheapest). Recurse to the top and the root carries the cost of the cheapest complete attack. The reason `min` appears at OR and not `max` is that the *attacker* chooses which alternative to use, never the defender, so the defender inherits whichever branch is easiest. Emptying a rented self-storage unit needs the gate PIN AND the unit padlock AND a camera blind window: those three add up, and calling the branch cheap because the padlock alone is cheap is the classic error, since a conjunction has no weakest link. Across alternatives, the opposite holds: the tree is only as strong as its cheapest complete path.

go deeper

for a junior

Be ready to say which operator goes with which node type: all children required means add, any child sufficient means take the smallest. Knowing that the root ends up holding the cheapest whole attack is enough at this level.

for a middle

Explain the mechanics on a small tree you draw yourself, bottom-up, and justify why OR takes a minimum rather than a maximum by pointing at who does the choosing. Expect to be handed three numbers and asked for the parent value.

for a senior

Show where the arithmetic misleads in real trees: shared subgoals double-counted through an AND, fixed costs presented as per-attempt costs, and a root that only moves to the second-cheapest branch when you close the first. Report the path, not just the number.

for a principal

Own the reporting convention. Decide whether your organisation reports a single root number, a named cheapest path with its runner-up, or nothing at all, and be able to argue why a bounded weakest-link claim is more defensible to a design review than a confident-looking aggregate score.

## What propagation is computing An attack tree states one attacker goal at the root and decomposes it downward. Every internal node is either an **AND** node — all children must be achieved for the parent to be achieved — or an **OR** node — any single child is sufficient. Leaves are concrete attacker actions. Once the leaves are annotated with an attribute (money, hours, required skill, chance of being noticed), *propagation* is the arithmetic that lifts those leaf annotations up to the root. For a cost-like attribute — one where lower is better for the attacker and where effort accumulates — the two rules are: - **AND node → sum the children.** The attacker has to pay for all of them. - **OR node → minimum of the children.** The attacker only pays for the one they pick, and a rational attacker picks the cheapest. Evaluate bottom-up and the number that lands at the root is the cost of the **cheapest complete attack**. ## Worked example: the AND rule A self-storage facility, adversary a walk-in local, asset the goods in a rented unit. To empty a unit unnoticed, all three of these are required: ``` AND Empty a unit without being stopped |-- Get through the perimeter gate (obtain a resident PIN) 150 |-- Defeat the unit padlock 40 +-- Act inside a camera blind window (learn patrol timing) 60 ``` (The figures are modeling estimates, not measurements.) The AND node carries **250**, not 40. The most common beginner error is to glance at the cheap padlock and call the whole branch cheap — importing the weakest-link intuition into a place it does not apply. A conjunction has no weakest link; it has a bill. ## Worked example: the OR rule A national tax-filing portal, goal "have a taxpayer's refund paid to an account I control". Three genuinely different routes sit under one OR, each with a different attacker position: - phish the taxpayer's portal credentials — an anonymous remote attacker; - compromise a third-party tax-preparer software vendor and ride its submission channel — a supply-chain position; - pay a contact-centre agent to change the bank details on one account — a bribed insider. If those cost roughly 30, 120,000 and 2,000, the OR node carries **30**. The expensive vendor branch contributes nothing to the node's value. That is not a bug in the notation: the attacker will simply not take it. ## Why minimum, and not maximum The direction of the operator encodes **who gets to choose**. At an OR node the attacker chooses, so the defender inherits the smallest value. You would take the maximum only if the defender could force which alternative the attacker was allowed to use — which never happens. This is the whole content of the *weakest-link reading*: a system's security guarantee is bounded by its cheapest complete path, not by its most impressive branch. A municipal e-voting pilot makes the point uncomfortable. Every cryptographic branch — forging ballot signatures, defeating the tally proof — costs a fortune. One branch is "spend twenty unobserved minutes with the tabulation laptop left in the hall overnight". The root takes the minimum, so the root is the laptop, and the asset at risk is audit truth. Every dollar spent on the expensive branches bought no guarantee at all until the cheap branch was closed. A corollary of `min`: closing the cheapest OR branch does not raise the root to the next-most-expensive branch you were proud of — it raises it to the **second cheapest**, which is often barely higher. ## Where the arithmetic quietly breaks - **Shared subgoals.** If the same leaf sits under two children of an AND, the structure is a graph, not a tree, and summing double-counts a one-off purchase. - **Non-independent children.** Buying the capability for one child can make its sibling nearly free; the sum then overstates. - **Fixed versus marginal cost.** A large one-off outlay amortised over many targets is not the same number as a per-attempt cost, and the tree records only one of them. - **Non-numeric annotations.** Ordinal labels do not add: summing "medium" and "low" at an AND node has no defined meaning. - **Estimate provenance.** `min` presumes the attacker enumerates the same alternatives you drew and values them the way you did. Branches you never drew are silently priced at infinity. ## Reading the result The root value is a **lower bound on attacker effort** — the strongest honest statement the tree supports. It is not a prediction of what will happen, and it is not a severity score. Reported to a design review, it is best phrased as a named path plus its cost, so the number stays attached to a concrete sequence of actions rather than floating free.

  • If two branches of an AND node depend on the same purchased capability, what does summing get wrong?
    It double-counts. The sum rule assumes children are independent line items, but if one toolkit or one stolen credential satisfies two children, the attacker pays once. The structure is really a graph with a shared node, and the honest fix is to price the shared subgoal once and note the dependency, rather than letting the sum inflate the branch and hide a cheap path.
  • Once every branch is costed, what does the root value let you say about the design?
    Only that no attack is cheaper than that number — a lower bound on effort. It is a weakest-link statement: on an e-voting result-integrity tree where every cryptographic branch is expensive and one branch is unsupervised physical access to the tabulation machine, the root is the physical branch. The expensive branches contribute nothing to the guarantee while a cheaper complete path exists.
  • What happens to the root if you close the cheapest OR branch?
    It rises to the second-cheapest branch, not to the level of the branch you were most confident in. Because OR takes a minimum, the improvement is bounded by whatever the next alternative costs, which is frequently only marginally more. That is why the root should always be reported with the runner-up path beside it.

Two locks on the same door add up: you pick both. Two different doors into the same room do not add up: you walk through whichever is easier and the other one never costs you anything.

saying these in an interview costs you the question

  • Taking the minimum at an AND node
  • Summing the children of an OR node
  • Calling an AND branch cheap because one child is cheap
  • Assuming the defender chooses which alternative is used
  • Treating the root value as a prediction of the attack
  • Adding costs of children that share one purchase

context

open as a page

On an attack tree, what attributes besides cost annotate a node, and why keep them separate?

level: middleimportance: must knowfreq 46%

basics

~20 s

Annotate each leaf with independent attributes: money, skill level, elapsed time, required access, equipment and detectability. Collapsing them into one number hides that a step can be cheap in cash yet demand rare skill or insider access nobody can buy.

open as a page

How do you turn a user story into an evil user story a developer can act on?

level: middleimportance: must knowfreq 60%

basics

~20 s

Keep the three story clauses and make each hostile: the role becomes a named attacker persona, the capability becomes what they want the system to allow, and the benefit becomes their payoff. The asset stays in the final clause.

open as a page

In an attack tree, what separates a usable concrete-action leaf from a category leaf?

level: middleimportance: must knowfreq 62%

basics

~20 s

A concrete-action leaf names one specific thing an attacker does on this system, specific enough to cost and to defend. A category leaf such as 'obtain a credential' only restates the sub-goal above it, hides the real work, and maps to no control.

open as a page

How do you turn an abuse case into an acceptance criterion and then an automated negative test?

level: middleimportance: must knowfreq 62%

basics

~10 s

Restate the attacker's goal as a must-not statement with an observable outcome, then write a test that runs from the adversary's position and asserts the refusal, the unchanged state, and the recorded evidence.

open as a page

How do you rank candidate mitigations using an attack tree's cheapest-path cost?

level: middleimportance: must knowfreq 48%

basics

~20 s

Re-cost the whole tree with each control applied and compare the rise in the root's cheapest-path value, not the rise on the node the control touches. Then weigh that rise against what the control costs you to build and run.

open as a page

How do AND and OR branches in an attack tree change where you spend defensive effort?

level: middleimportance: must knowfreq 62%

basics

~20 s

An OR node means any one child suffices, so the branch costs whatever the cheapest child costs and hardening only some children buys nothing. An AND node needs every child, so breaking one conjunct closes the whole branch.

open as a page

Someone opens an attack tree with the root 'stored XSS in the profile page' - what is wrong with it?

level: juniorimportance: should knowfreq 48%

basics

~20 s

That root names a vulnerability, not an attacker objective. An attack tree's root must state what the attacker wants to achieve - post as a moderator to the whole membership - leaving the flaw as one branch beneath it.

open as a page

In an attack-tree library, what is a reusable subtree and when do you re-attach one?

level: middleimportance: should knowfreq 38%

basics

~20 s

A reusable subtree is one sub-goal decomposed once - say 'gain write access to the build runner' - and re-attached under many attack trees by reference. Re-attach when the sub-goal genuinely recurs with the same shape.

open as a page

Why is an attack tree's cheapest path often not the attack you should expect?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Cheapest-path propagation assumes an attacker minimising your cost estimate for one attempt. Real adversaries optimise repeatability, exposure risk and capability they already own, so the attack you actually see is often a costlier branch run at volume.

open as a page

Two attack-tree branches reach the same HR records — one bulk export, one 400 single lookups. Which annotations separate them?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Detectability and elapsed time. For a caseworker with legitimate access, cost, skill, equipment and required access are near identical on both branches; the slow branch trades months of wall-clock time for a much lower chance of being noticed.

open as a page

When do you stop pushing a branch of an attack tree deeper?

level: seniorimportance: should knowfreq 48%

basics

~20 s

Stop when the node already names an action you can cost and defend, when every child would resolve to the same control, or when further detail describes work you cannot influence. Depth is a budget, and uneven depth is expected.

open as a page

How do you keep a negative test from passing without proving the control works?

level: seniorimportance: should knowfreq 44%

basics

~20 s

Pair every negative assertion with a positive control in the same run, assert the exact refusal the design chose plus unchanged state and a denial record, and confirm the test fails when the guard is disabled.

open as a page

After a control kills an attack tree's cheapest branch, why might the root cost barely rise?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Because the attacker displaces onto the next-cheapest branch. An OR node takes the minimum over alternatives, so removing one path only helps by the gap to the runner-up — which is often small, and often reached by a completely different adversary.

open as a page

You re-attach one 'obtain an operator credential' subtree to three internal consoles - how do you parameterise it per console?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Share the branch structure; set everything measurable per console - leaf cost, skill, detectability, feasibility. Prune branches a console lacks, raise leaves an existing control blocks, then re-propagate: the cheapest path can differ per console.

open as a page

How do you keep evil user stories in a shared product backlog when they have no happy path?

level: principalimportance: should knowfreq 41%

basics

~20 s

Attach each evil user story to the feature story it inverts so it is sized in the same slice, and express its value as a capability removed from the attacker rather than one added for a user. A separate security backlog ages and dies.

open as a page

What makes the attacker persona behind an evil user story useful rather than a caricature?

level: seniorimportance: nice to knowfreq 33%

basics

~20 s

A useful attacker persona states the access the person already holds, what they want from this specific system, what counts as good enough for them, and what they will not risk. A caricature states only a label.

open as a page

How do you fix an attack tree level where one sibling is a broad sub-goal and the next is a single keystroke?

level: seniorimportance: nice to knowfreq 31%

basics

~20 s

Rewrite the level so every sibling sits at the same grain, each naming a state the attacker still has to reach. Demote the over-specific child under the sub-goal it serves; promote anything vaguer than its neighbours.

open as a page

In an attack tree, why does propagating cost and time separately give an unreal path?

level: principalimportance: nice to knowfreq 27%

basics

~20 s

Each attribute's minimum can land on a different OR branch, so the root reports one branch's money beside another branch's hours. That combination is not an attack anyone can run. Propagate whole annotated paths, not independent columns of numbers.

open as a page

Your team's attack-tree nodes carry point costs like $180,000 that nobody can source. What do you change?

level: principalimportance: nice to knowfreq 31%

basics

~20 s

Replace unsourceable point figures with a few named qualitative bands and record where each value came from. A precise-looking number nobody can trace survives review because it has digits, and it makes a guess look like evidence.

open as a page

A sub-goal repeats under three branches of your attack tree: duplicate, share, or lift it?

level: principalimportance: nice to knowfreq 31%

basics

~20 s

Duplicate only when the copies genuinely differ under each parent. If it is the same work, share one node or lift it into its own tree with reference stubs, and read the repetition itself as a chokepoint where one control cuts three paths.

open as a page

How do you handle the steps of an abuse case that no automated test can cover?

level: principalimportance: nice to knowfreq 28%

basics

~10 s

Split the narrative into steps, automate the technical invariants, and keep each human-dependent step visible in the model with a stated reason and a named substitute exercise instead of quietly deleting it.

open as a page

Your fourth control on one attack-tree branch barely raises attacker cost — where do you spend next?

level: principalimportance: nice to knowfreq 26%

basics

~20 s

Stop stacking on that branch. Once a path is hardened past the next-cheapest alternative, further controls there buy nothing at the root. Spend on whichever branch now sets the root cost, or on detection and response instead of prevention.

open as a page

A shared attack-tree subtree no longer fits every consumer as their systems diverge - how do you keep the library honest?

level: principalimportance: nice to knowfreq 18%

basics

~10 s

Give each shared subtree a named owner and a recorded consumer list, review it whenever a consumer's architecture changes, fork when branches diverge in shape, and retire subtrees no live system matches.

open as a page