new(rules): detect security tool impairment in containers (T1562.001)#367
new(rules): detect security tool impairment in containers (T1562.001)#367JayKnowSo wants to merge 1 commit into
Conversation
Signed-off-by: DevNow <worklife0524@gmail.com>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: JayKnowSo The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
leogr
left a comment
There was a problem hiding this comment.
Hey @JayKnowSo
Thanks for tackling this!
The bulk of my feedback is around substring-matching precision and a couple of output-template alignments, see inline 👇
Otherwise, SGMT.
🙏
| (proc.args contains "falco" or proc.args contains "auditd")) | ||
| ) | ||
| and not user_known_security_tool_disable_activities | ||
| output: Security tool disabled or firewall rules cleared in container | args=%proc.args 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 container_id=%container.id image=%container.image.repository |
There was a problem hiding this comment.
| output: Security tool disabled or firewall rules cleared in container | args=%proc.args 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 container_id=%container.id image=%container.image.repository | |
| 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 |
A few alignments with the style guide and our other rules:
- Adding
exe_flags=%evt.arg.flags, since the style guide recommends including it forspawned_process-only rules (https://falco.org/docs/rules/style-guide/#output) - Dropping
args=%proc.args, since it's redundant with%proc.cmdline(which already includes the args) - Dropping
container_id=%container.id image=%container.image.repository. No other rule in the tree includes these fields in upstream output (quick check:grep "%container.id\|%container.image" rules/*.yamlreturns only this PR's line). The convention is to let Falco'sappend_outputconfig (or the-pcoption) add container metadata downstream, keeping rule outputs minimal.
| (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")) |
There was a problem hiding this comment.
| (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 isreload, but bothstopandfalcosubstrings 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.
| (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")) |
There was a problem hiding this comment.
| (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.
| output: Security tool disabled or firewall rules cleared in container | args=%proc.args 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 container_id=%container.id image=%container.image.repository | ||
| priority: | ||
| WARNING | ||
| tags: [maturity_incubating, container, process, network, mitre_defense_evasion, T1562.001] |
There was a problem hiding this comment.
| tags: [maturity_incubating, container, process, network, mitre_defense_evasion, T1562.001] | |
| tags: [maturity_incubating, container, process, mitre_defense_evasion, T1562.001] |
network here is a bit inconsistent with the rest of the repo. All ~20 rules currently carrying the network tag fire on actual network sockets/connections (evt.type=connect, packet socket creation, redirect of stdout/stdin to a network fd) or on the execution of network-traffic tools (nc, nmap, tcpdump). This rule fires on process exec + argument inspection on firewall/service-manager binaries, with no network fields in either condition or output. Dropping network keeps the tag set aligned with project usage.
Summary
Adds a detection rule for MITRE ATT&CK T1562.001 (Impair Defenses: Disable or Modify Tools) scoped to container workloads.
What this detects
iptables/ip6tablesflush or delete-chain commands inside a containersystemctl stoptargeting security daemons (falco, auditd, sysdig, osquery)service stoptargeting falco or auditdWhy this matters
T1562 was the most prevalent defense evasion technique in malware campaigns in 2025. After achieving initial execution in a container (T1059), adversaries commonly disable runtime security tooling before lateral movement. No existing rule in stable, incubating, or sandbox tiers covers this technique for container workloads.
MITRE ATT&CK
https://attack.mitre.org/techniques/T1562/001/
False positives
Tunable via
user_known_security_tool_disable_activitiesmacro. Legitimate iptables usage in containers is rare and should be explicitly allowlisted.Testing
Rule fires on:
iptables -F,systemctl stop falco,service stop auditdexecuted inside a running container.