falco: add cryptominer/runtime-security scanner wired into netdata

Detects unauthorized miners (and other runtime threats) via Falco's
syscall/eBPF monitoring, following the 2026-08-06 gitea/xmrig
compromise. Wired into netdata rather than a new notification channel:
Falco exposes a Prometheus /metrics endpoint, netdata scrapes it, and a
new health.d alarm pages through netdata's already-configured Telegram
bot - no new alerting infra needed.

Includes a custom process-name rule for known miner binaries (the stock
Stratum-protocol rule wouldn't have caught the actual gitea incident,
which used a bare host:port with no scheme prefix), an outbound
miner-pool-port rule as a second layer, and rule_matching: all in the
Falco config - without it, Falco silently drops all but the first
matching rule per event, which would have suppressed our custom rule
whenever a stock rule also matched the same process.
This commit is contained in:
2026-08-08 17:41:20 +00:00
parent 225e872fe9
commit ba925fe734
5 changed files with 125 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
# Custom rule: catch known cryptominer binaries by process name directly.
# Added after the 2026-08-06 gitea/xmrig compromise, where the miner was
# invoked as `--url=host:port` with no "stratum+tcp" scheme prefix, which
# would NOT have matched Falco's stock "Detect crypto miners using the
# Stratum protocol" rule. Matching the binary name is the reliable signal.
- list: miner_binary_names
items: [
xmrig, xmrig-notls, xmr-stak, xmr-stak-cpu, xmr-stak-rx,
minerd, cpuminer, ccminer, cgminer, bfgminer,
nanominer, t-rex, trex, teamredminer, phoenixminer, lolminer,
ethminer, nbminer, gminer, srbminer, xmrigMiner,
]
- rule: Detect crypto miner binary execution
desc: >
A process matching a known cryptocurrency miner binary name was executed.
Catches unauthorized miners even when the command line doesn't use a
stratum+tcp:// style URL.
condition: >
spawned_process and proc.name in (miner_binary_names)
output: >
Cryptominer binary execution detected
(user=%user.name command=%proc.cmdline container=%container.name
image=%container.image.repository pid=%proc.pid)
priority: CRITICAL
tags: [miners, process, mitre_impact]
+28
View File
@@ -0,0 +1,28 @@
# Supplementary defense-in-depth: outbound connections to common mining-pool
# ports. NOTE: this image's shipped falco_rules.yaml has no built-in
# miner/stratum/pool rules to "enable" (checked directly - none exist), so
# this is written from scratch rather than overriding a stock rule. It's
# a weaker signal than miner-detect.yaml's process-name match (our actual
# incident used port 10128, which isn't in this list - pools use arbitrary
# ports), kept anyway as a second layer.
- list: miner_pool_ports
# Kept to well-corroborated fixed mining-pool ports only, all well below
# the Linux ephemeral port range (32768-60999). Two entries originally
# added here without solid sourcing (45560, 45700) fell inside that
# ephemeral range and produced an immediate false positive against
# qbittorrent_eXoDOS's own randomly-assigned outbound source port -
# removed.
items: [3333, 3334, 4444, 5555, 5556, 7777, 8888, 9999, 14444]
- rule: Detect outbound connection to common miner pool port
desc: Outbound connection to a TCP port commonly used by cryptomining pools.
condition: >
outbound and evt.type in (connect, sendto, sendmsg)
and fd.rport in (miner_pool_ports)
output: >
Outbound connection to common miner-pool port
(user=%user.name command=%proc.cmdline connection=%fd.name
container=%container.name image=%container.image.repository)
priority: WARNING
tags: [miners, network, mitre_impact]
+13
View File
@@ -0,0 +1,13 @@
# Tune out stock-rule false positives observed on this specific host, so the
# broad netdata "any Falco match" alarm only pages for things worth paging
# for. Uses Falco's own user_* customization macros rather than disabling
# whole rules, so the underlying security check stays active for everything
# else. Add entries here as new noisy defaults turn up - don't let this list
# grow into blinding Falco to anything actually meaningful.
# "Sensitive file opened for reading by non-trusted program" fired every
# ~10s from inbox-zero-db's pg_isready healthcheck touching /etc/shadow -
# NSS/libc user-lookup behavior during process init, not credential
# harvesting. Scoped to just this binary, not a blanket rule disable.
- macro: user_known_read_sensitive_files_activities
condition: (proc.name = pg_isready)