Found during live testing: netdata's cloud-provider auto-detection runs curl --fail -s -m1 --noproxy * http://169.254.169.254 on every startup/reconnect to check whether the host is in AWS/GCP/Azure - standard monitoring-agent behavior, not a bug. Without this exception the rule would have paged every time netdata restarts. Scoped to netdata's own curl specifically so any other connection from that container still alerts.
48 lines
2.5 KiB
YAML
48 lines
2.5 KiB
YAML
# Custom rule, adapted from falcosecurity/rules' Incubating ruleset (not
|
|
# shipped in this Falco image). This host has no cloud provider, so
|
|
# 169.254.169.254 (the AWS/GCP/Azure instance-metadata IP) has zero
|
|
# legitimate traffic ever - any connection attempt to it is a strong
|
|
# signal, either SSRF probing or a container image/script that assumes a
|
|
# cloud environment. Near-zero false-positive risk, so this stays a plain
|
|
# CRITICAL with no scoped exception - if something legitimate ever needs
|
|
# it, add a proc/container-scoped exception here rather than disabling.
|
|
#
|
|
# Deliberately does NOT use the stock "outbound" macro: that macro
|
|
# requires evt.rawres >= 0 (or EINPROGRESS), i.e. a connection that
|
|
# actually succeeded/is in progress. Since this host has no route to
|
|
# 169.254.169.254 at all, any attempt - malicious or a test - fails
|
|
# instantly at the kernel level (ENETUNREACH) and would never satisfy
|
|
# "outbound". The interesting signal here is the attempt itself, not
|
|
# whether it succeeded, so this matches the raw connect/send syscalls
|
|
# directly. Verified live: a wget to this address from a test container
|
|
# (which fails to connect, as expected with no route) still triggers this
|
|
# rule.
|
|
#
|
|
# One genuine false positive found during testing: netdata's own
|
|
# cloud-provider auto-detection runs `curl --fail -s -m 1 --noproxy *
|
|
# http://169.254.169.254` on every startup/reconnect, to check whether the
|
|
# host is running in AWS/GCP/Azure (standard monitoring-agent behavior,
|
|
# not a cloud provider assumption bug). Scoped to netdata's own curl
|
|
# specifically, not the whole container, since netdata making any OTHER
|
|
# connection to this address would still be worth knowing about.
|
|
- macro: known_cloud_metadata_probes
|
|
condition: (container.name = "netdata" and proc.name = curl)
|
|
|
|
- rule: Contact cloud metadata service from container
|
|
desc: >
|
|
Detects attempts to communicate with a cloud instance metadata service
|
|
(169.254.169.254) from a container. This host has no cloud provider,
|
|
so this endpoint should never see legitimate traffic - treat any hit
|
|
as SSRF probing or malware/scripts written for a cloud environment.
|
|
condition: >
|
|
evt.type in (connect, sendto, sendmsg)
|
|
and container
|
|
and fd.sip="169.254.169.254"
|
|
and not known_cloud_metadata_probes
|
|
output: >
|
|
Outbound connection to cloud instance metadata service
|
|
(user=%user.name command=%proc.cmdline connection=%fd.name
|
|
container=%container.name image=%container.image.repository pid=%proc.pid)
|
|
priority: CRITICAL
|
|
tags: [network, credential_access, mitre_credential_access]
|