skip to content

Three different shell spellings of one action on a CI runner: one ATT&CK technique or three?

level: seniorimportance: should knowfreq 42%

answer

  1. Classify by mechanism, not appearance
  2. State the invariant each variant needs
  3. Does the parent description still hold
  4. Different interpreter, different sub-technique
  5. No interpreter, different technique entirely

basics

~20 s

One technique and three procedures, provided all three still depend on the same mechanism. Classify by what the action cannot do without, not by how it was written; a new sub-technique needs a mechanism that differs in kind, not a different string.

solid answer

~50 s

Test the invariant, not the text. If all three spellings still rely on a Unix shell interpreting operator-supplied commands, they are one technique — `T1059.004` — and three procedures, because the class is named by the dependency and the dependency did not change. A different sub-technique is warranted only when the mechanism differs in kind: switching to a Python interpreter moves it to `T1059.006`, and a Windows command shell would be `T1059.003`. If one of the three drops the interpreter altogether and drives the platform's own interface directly, it leaves `T1059` entirely and belongs under a different technique. So the honest answer is not a reflex *always one technique*; it is *read what each one requires and see whether the parent description still holds*. That is also the practical test for whether a variant deserves cataloguing at all.

go deeper

for a junior

Recall that the number of distinct commands does not change the number of techniques. Three spellings of one shell action are three procedures under one identifier.

for a middle

Explain the test rather than the verdict: name what each variant requires, check whether the parent technique's description still holds, and say what would move a variant to a sibling sub-technique.

for a senior

Demonstrate the boundary judgment both ways — when variants collapse into one class, and when a variant has genuinely stopped depending on the interpreter and so leaves it. Say which observation would change your classification.

for a principal

Own why the discipline matters beyond one runner. A class that grows an entry per observed string stops predicting anything, and any commitment written against it inherits that emptiness.

## The question behind the question An interviewer showing you three variants is testing whether you classify by mechanism or by appearance. Classifying by appearance produces a catalogue that grows forever and predicts nothing; classifying by mechanism produces a small, stable set that tells you what the adversary depends on. ## The three spellings One operator, one afternoon, one self-hosted CI runner they already have privilege on: 1. a shell started directly by a job step; 2. the same shell started by a small wrapper script committed next to the job; 3. the same shell taking its commands from an environment variable the runner already exports. ## The test to apply Ask three things of each variant, in this order. **What does it require in order to work?** All three require a Unix shell present and executable in the job context and something able to hand it operator-supplied input. Identical. That requirement is what `T1059.004` names. **Does the parent technique's description still hold?** `T1059` Command and Scripting Interpreter describes abusing interpreters to execute commands, scripts or binaries. Yes for all three. **Does anything about the variant change what an adversary must possess?** No. The wrapper script and the environment variable are packaging. The operator needed nothing new to produce them. Three procedures. One technique. Nothing in the catalogue changes, and nothing should. ## When a variant genuinely is something else The interesting half of this question is the boundary, and a strong candidate goes there unprompted. | The variant | Where it lands | Why | |---|---|---| | Same commands, Python instead of the shell | `T1059.006` | a different interpreter is a different sub-technique of the same parent | | Same commands, a Windows command shell | `T1059.003` | different platform mechanism, separately catalogued | | No interpreter — the action driven through the platform's own interface | not `T1059` | the parent's description no longer holds; the dependency is gone | That last row is the one that matters operationally, because it is the case where an adversary genuinely has changed what they depend on, and the class you were reasoning about no longer describes them. ## Why ATT&CK splits sub-techniques at all A sub-technique exists where a behaviour is a distinguishable way of achieving the parent — distinguishable in the mechanism it uses, and therefore in what removes it. That criterion is about kind, not about volume of variants. Three ways of typing the same shell invocation are not distinguishable in mechanism and would not earn a split even if a thousand of them were reported, which is exactly why the catalogue leaves the procedure level unnumbered rather than growing decimals forever. ## The judgment this demands of you When someone brings you a fourth variant and asks whether it is *new*, the answer is not a count. It is: *state the invariant. If the invariant is unchanged, it is a procedure and it teaches you nothing new about what the operator depends on. If the invariant changed, say which dependency moved and where the action now sits.* Getting this wrong in the permissive direction — calling every spelling a new technique — makes any claim about an adversary meaningless, because the class you name no longer predicts anything. Getting it wrong in the strict direction — insisting everything is still `T1059` — hides the moment when the operator stopped needing an interpreter at all, which is the moment your reasoning about them went stale. ## Saying it cleanly *One technique, three procedures, because all three still need a shell fed operator-supplied input. I would change my answer if a variant swapped interpreters — that is a sibling sub-technique — or dropped the interpreter for a direct platform interface, which leaves the parent altogether.*

  • When does a respelling genuinely become a different sub-technique?
    When the mechanism differs in kind rather than in text. Swapping the Unix shell for Python moves it to `T1059.006`; a Windows command shell is `T1059.003`. The test is whether what the adversary must possess has changed, since sub-techniques are split where the mechanism — and therefore what removes it — is distinguishable.
  • What if the fourth variant stops using an interpreter altogether?
    Then it leaves `T1059`. The parent describes abusing an interpreter to execute commands, and if the action is driven through the platform's own interface instead, that description no longer holds. This is the case worth catching, because it is the one where the adversary really did change what they depend on.
  • A colleague wants to log each new spelling as a new technique. What is the harm?
    Any claim about the adversary stops predicting anything. The value of a class is that it names a dependency; if the class grows one entry per string, it names nothing and the count of techniques becomes a count of how much you happened to see. It also buries the genuine boundary crossing among the noise.

saying these in an interview costs you the question

  • Counts distinct command lines as distinct techniques
  • Insists everything stays T1059 no matter the mechanism
  • Cannot state what the variant requires to work
  • Splits a sub-technique on string differences alone
  • Misses that dropping the interpreter leaves the parent

context