Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions rules/falco-incubating_rules.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,36 @@
# when more than one event type is involved because some event will populate
# the filtercheck and others will always return <NA>. It would be better to use
# a more generic filter like `fs.path.*`
- macro: user_known_security_tool_disable_activities

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May you move the new macro and rule below the Delete or rename shell history rule?

The # todo!: block right above belongs to that rule - it is about avoiding evt.arg* in the output when a rule spans more than one event type. Inserting here re-parents the comment to your macro, which is quite confusing, since your rule is spawned_process-only and exe_flags=%evt.arg.flags is exactly the right thing to have there.

condition: (never_true)

- rule: Defense Tool Disabled or Modified in Container
desc: >
Detect attempts to disable or modify security tooling inside a running container,
including flushing firewall rules via iptables or stopping security daemons such
as falco, auditd, or sysdig. Adversaries impair defenses after achieving initial
execution to operate undetected before lateral movement.
Maps to MITRE ATT&CK T1562.001 (Impair Defenses: Disable or Modify Tools).
condition: >
spawned_process and container
and (
(proc.name in (iptables, ip6tables) and
(proc.args contains "-F" or proc.args contains "--flush" or
proc.args contains "-X" or proc.args contains "--delete-chain"))
Comment on lines +1023 to +1025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(proc.name in (iptables, ip6tables) and
(proc.args contains "-F" or proc.args contains "--flush" or
proc.args contains "-X" or proc.args contains "--delete-chain"))
(proc.name in (iptables, ip6tables) and
(proc.args startswith "-F" or proc.args startswith "--flush" or
proc.args startswith "-X" or proc.args startswith "--delete-chain" or
proc.args contains " -F" or proc.args contains " --flush" or
proc.args contains " -X" or proc.args contains " --delete-chain"))

Same precision concern as the systemctl block. proc.args contains "-F" matches the substring -F anywhere in the args, including inside chain names or comment text. Combining startswith for first-position flags with contains " -F" (leading space) for later positions covers both placements while staying anchored to whitespace boundaries - same pattern as falco_rules.yaml:849-851 and falco-incubating_rules.yaml:1162-1165.

Comment on lines +1023 to +1025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(proc.name in (iptables, ip6tables) and
(proc.args contains "-F" or proc.args contains "--flush" or
proc.args contains "-X" or proc.args contains "--delete-chain"))
(proc.name in (iptables, ip6tables) and
(proc.args startswith "-F" or proc.args contains " -F" or
proc.args startswith "-X" or proc.args contains " -X" or
proc.args contains "--flush" or proc.args contains "--delete-chain"))

I have dug a bit more into this since my previous round, and it is worse than I described back then.

proc.args contains "-F" is an unanchored substring search, so it also matches any chain name containing -F. Those are everywhere in container networking:

  • iptables -A KUBE-FORWARD ... (kube-proxy) 👉 KUBE-FORWARD contains -F
  • iptables -N KUBE-FIREWALL (kubelet) 👉 KUBE-FIREWALL contains -F
  • iptables -A cali-FORWARD ... (Calico) 👉 same story

-X has the same problem with the KUBE-SVC-<hash> / KUBE-SEP-<hash> chains, since the base32 hash can start with X.

So, as written, the rule fires on routine CNI and kube-proxy activity in pretty much any Kubernetes cluster.

The suggestion anchors the short flags on a whitespace boundary (startswith for the first position, contains " -F" for the later ones). That is the convention we already use elsewhere, see Netcat Remote Code Execution in Container in falco_rules.yaml (proc.cmdline contains " -e") and the curl_download macro further down in this same file. --flush and --delete-chain are long enough to be unambiguous, so plain contains is fine for them.

or
(proc.name = systemctl and proc.args contains "stop" and
(proc.args contains "falco" or proc.args contains "auditd" or
proc.args contains "sysdig" or proc.args contains "osquery"))
or
(proc.name = service and proc.args contains "stop" and
(proc.args contains "falco" or proc.args contains "auditd"))
Comment on lines +1027 to +1032

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(proc.name = systemctl and proc.args contains "stop" and
(proc.args contains "falco" or proc.args contains "auditd" or
proc.args contains "sysdig" or proc.args contains "osquery"))
or
(proc.name = service and proc.args contains "stop" and
(proc.args contains "falco" or proc.args contains "auditd"))
(proc.name = systemctl and
(proc.args startswith "stop " or proc.args contains " stop ") and
(proc.args contains " falco" or proc.args contains " auditd" or
proc.args contains " sysdig" or proc.args contains " osquery"))
or
(proc.name = service and
(proc.args startswith "falco " or proc.args startswith "auditd ") and
(proc.args endswith " stop" or proc.args contains " stop "))

The current proc.args contains "stop" and (proc.args contains "falco" or ...) is an unanchored substring search on the full joined args. Both substrings just have to appear anywhere in the string, so the rule can fire on:

  • systemctl status mystop.service (if "falco" happens to appear elsewhere, e.g., in an env var path the args carry)
  • systemctl reload falco-helper-stopwatch.service (verb is reload, but both stop and falco substrings match)

Our convention for short-token matching is whitespace anchoring, see the netcat rule at falco_rules.yaml:849-851 (proc.args contains "-e ", etc.). The suggestion above anchors both the verb and the daemon name with leading/trailing whitespace, matching realistic usage like systemctl stop falco, systemctl --no-block stop falco, service falco stop while rejecting the substring-noise cases.

Comment on lines +1027 to +1032

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(proc.name = systemctl and proc.args contains "stop" and
(proc.args contains "falco" or proc.args contains "auditd" or
proc.args contains "sysdig" or proc.args contains "osquery"))
or
(proc.name = service and proc.args contains "stop" and
(proc.args contains "falco" or proc.args contains "auditd"))
(proc.name = systemctl and
(proc.args startswith "stop " or proc.args contains " stop ") and
(proc.args contains "falco" or proc.args contains "auditd" or
proc.args contains "sysdig" or proc.args contains "osquery"))
or
(proc.name = service and
(proc.args endswith " stop" or proc.args contains " stop ") and
(proc.args startswith "falco" or proc.args startswith "auditd"))

Same anchoring concern as above, milder here since both substrings have to match.

proc.args contains "stop" matches the verb anywhere in the args, so read-only queries like systemctl list-units --state=stopped 'falco*' fire too, since stopped contains stop. Anchoring on whitespace keeps systemctl stop falco and systemctl --no-block stop falco while dropping that class.

For service, the SysV syntax is service <unit> <verb> (i.e., service falco stop), so endswith " stop" is the natural anchor there.

Btw, systemctl disable and systemctl mask are arguably stronger signals than stop, since they survive a reboot. Not asking for it in this PR, just something we may want to add later 😇

)
and not user_known_security_tool_disable_activities
output: Security tool disabled or firewall rules cleared in container | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
priority:
WARNING
Comment on lines +1036 to +1037

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
priority:
WARNING
priority: WARNING

Nit. 27 of the 31 existing rules in this file keep priority inline. The rule right below happens to be one of the 4 exceptions, so it is an easy one to pick up by accident.

tags: [maturity_incubating, container, process, mitre_defense_evasion, T1562.001]

- rule: Delete or rename shell history
desc: >
Detect shell history deletion, frequently used by unsophisticated adversaries to eliminate evidence.
Expand Down
Loading