Files
DECNET/rules/ttp/R0012.yaml
anti b1fe1f9403 feat(ttp): E.3.8 R0001-R0030 command cohort
30 YAMLs for the shell/command rule cohort per Appendix B (rules/ttp/).
Splits into engine-active (R0007-R0029, regex on command_text /
raw_url / user_agent) and lifter-bound (R0001-R0006, R0030 — the
v0 RuleEngine cannot count auth attempts, do identity rollups, or
parse fingerprint blobs; the BehavioralLifter / IdentityLifter /
CredentialLifter consume them by rule_id at E.3.9 / E.3.13).

test_command_rules.py asserts:
- every R000N has a YAML that compiles
- lifter-bound rules NEVER fire from the v0 engine (regression
  guard against a YAML drifting into a regex match.spec)
- engine-active rules meet their Appendix-C precision target
  against the seed corpus (≥0.95 high-conf, ≥0.80 medium)

Conftest fixes: precision_engine moved to module-scope so module-
scope precomputed dispatch fixture (fired_by_label) can request it;
_RULES_DIR path bumped from parents[2] to parents[3] so the loader
resolves the project root regardless of pytest cwd; make_event
synthesizes attacker_uuid so TTPTag's anchor invariant is satisfied.

Seed corpus broadened: positive examples for every regex rule plus
6 negative examples across innocuous shell verbs (ls, echo, cd, ps,
df, free) so FPs surface in precision rather than passing vacuously.
2026-05-01 09:16:38 -04:00

18 lines
466 B
YAML

rule_id: R0012
rule_version: 1
name: ingress_tool_transfer
description: |
wget/curl/tftp/scp pulling a payload from a remote URL. Anchors
on the verb-then-URL shape; bare 'curl' alone won't fire.
applies_to:
- command
match:
field: command_text
pattern: '(?i)\b(wget|curl|tftp|scp|ftpget)\s+(?:-\S+\s+)*(?:[^|;\s]+\s+)*https?://|\b(wget|curl)\s+-O\s'
emits:
- tactic: TA0011
technique_id: T1105
confidence: 0.85
evidence_fields:
- command_text