From f5c51cd71cd50bc1b237c1a2fd0a419b6c9ec6d1 Mon Sep 17 00:00:00 2001 From: Stefan Reimer Date: Tue, 7 Nov 2023 16:31:20 +0000 Subject: [PATCH] falco version bump --- kubezero/falco/:w | 73 - kubezero/falco/APKBUILD | 29 +- kubezero/falco/falco_rules.yaml | 2961 ++++---------------------- kubezero/falco/rules.patch | 73 +- kubezero/falco/zdt_falco_rules.yaml | 2964 ++++----------------------- 5 files changed, 825 insertions(+), 5275 deletions(-) delete mode 100644 kubezero/falco/:w diff --git a/kubezero/falco/:w b/kubezero/falco/:w deleted file mode 100644 index d8a4a63..0000000 --- a/kubezero/falco/:w +++ /dev/null @@ -1,73 +0,0 @@ -# Contributor: Stefan Reimer -# Maintainer: Stefan Reimer -pkgname=falco -pkgver=0.36.2 -pkgrel=0 -pkgdesc="Falco is the open source solution for runtime security for hosts, containers, Kubernetes and the cloud" -url="https://github.com/falcosecurity/falco" -arch="x86_64 aarch64" -license="AGPL-3.0" -makedepends="cmake linux-headers bash perl autoconf elfutils-dev libtool argp-standalone musl-fts-dev musl-libintl musl-obstack-dev - protobuf-dev jq-dev openssl-dev curl-dev c-ares-dev grpc-dev yaml-dev yaml-cpp-dev zlib-dev jsoncpp-dev re2-dev onetbb-dev@edge-community" -options="!check" -depends="falco-kernel~$pkgver" - -# Original config -# https://raw.githubusercontent.com/falcosecurity/rules/main/rules/falco_rules.yaml -# https://raw.githubusercontent.com/falcosecurity/falco/master/falco.yaml - -source=" - $pkgname-$pkgver.tar.gz::https://github.com/falcosecurity/falco/archive/refs/tags/$pkgver.tar.gz - alpine.patch - falco.patch - rules.patch - " - -prepare() { - [[ -d build ]] || mkdir build - - # Disable static binaries - patch -i $srcdir/alpine.patch -} - -build() { - cd build - - cmake \ - -DCPACK_GENERATOR=TGZ \ - -DCMAKE_BUILD_TYPE=Release \ - -DFALCO_VERSION=$pkgver \ - -DCMAKE_INSTALL_PREFIX=/usr \ - -DFALCO_ETC_DIR=/etc/falco \ - -DUSE_BUNDLED_DEPS=Off \ - -DBUILD_SHARED_LIBS=On \ - -DMUSL_OPTIMIZED_BUILD=On \ - -DBUILD_DRIVER=Off \ - -DBUILD_BPF=Off \ - -DBUILD_LIBSCAP_MODERN_BPF=Off \ - .. - - make falco falcoctl -} - -package() { - cd build - make DESTDIR="${pkgdir}" install - - # patch falco config - cd $pkgdir/etc/falco - patch -i $srcdir/falco.patch - patch -i $srcdir/rules.patch - - # We dont build anything on targets so remove sources - rm -rf $pkgdir/usr/src - rm -rf $pkgdir/usr/lib - rm -rf $pkgdir/usr/include -} - -sha512sums=" -a3fef235ab4f3121bd0400827712652530ec417498c44ada8b6bf565f7631d035673b53dad94ea6ae9c854d45202ed71b2771f19e0c92eea3fc3503e5b75b02e falco-0.36.2.tar.gz -8ff7a677f723f2d4a09808939500ddff81f15b8a62a2e091d8042765d105d30b67f9993d05ef129dfad6c866ea37d608a3ae9bc7e99730995542f8b5181ba594 alpine.patch -b152fcf6cd81895efa37797ab7ff1aac7350b5f51f2648aa9e3cce9d5ece55791ddf82c396e9da216293e2379a785a294cc972f28a91162dc5bc88ab09e1ab08 falco.patch -d8f71ca7c6d854a866826b3f2f5630b6f30448f794c4c5a56a9ea656ee03c3645a1cf7663b5e79d3ea63d4fab8bd44f91a80b1752c8239c8310efa08b495f2e2 rules.patch -" diff --git a/kubezero/falco/APKBUILD b/kubezero/falco/APKBUILD index b2eb0c1..23d7b4b 100644 --- a/kubezero/falco/APKBUILD +++ b/kubezero/falco/APKBUILD @@ -1,14 +1,18 @@ # Contributor: Stefan Reimer # Maintainer: Stefan Reimer pkgname=falco -pkgver=0.35.1 +pkgver=0.36.2 pkgrel=0 pkgdesc="Falco is the open source solution for runtime security for hosts, containers, Kubernetes and the cloud" url="https://github.com/falcosecurity/falco" arch="x86_64 aarch64" license="AGPL-3.0" -makedepends="cmake linux-headers bash perl autoconf elfutils-dev libtool argp-standalone musl-fts-dev musl-libintl musl-obstack-dev - protobuf-dev jq-dev openssl-dev curl-dev c-ares-dev grpc-dev yaml-dev yaml-cpp-dev jsoncpp-dev re2-dev" +makedepends="cmake linux-headers bash perl autoconf elfutils-dev libtool argp-standalone + musl-fts-dev + musl-libintl + musl-legacy-error + musl-obstack-dev + " options="!check" depends="falco-kernel~$pkgver" @@ -18,16 +22,12 @@ depends="falco-kernel~$pkgver" source=" $pkgname-$pkgver.tar.gz::https://github.com/falcosecurity/falco/archive/refs/tags/$pkgver.tar.gz - alpine.patch falco.patch rules.patch " prepare() { [[ -d build ]] || mkdir build - - # Disable static binaries - patch -i $srcdir/alpine.patch } build() { @@ -39,16 +39,14 @@ build() { -DFALCO_VERSION=$pkgver \ -DCMAKE_INSTALL_PREFIX=/usr \ -DFALCO_ETC_DIR=/etc/falco \ - -DMINIMAL_BUILD=On \ - -DUSE_BUNDLED_DEPS=Off \ + -DUSE_BUNDLED_DEPS=On \ -DMUSL_OPTIMIZED_BUILD=On \ -DBUILD_DRIVER=Off \ -DBUILD_BPF=Off \ -DBUILD_LIBSCAP_MODERN_BPF=Off \ .. - #-DBUILD_SHARED_LIBS=On \ - make falco falcoctl + make falco } package() { @@ -57,8 +55,8 @@ package() { # patch falco config cd $pkgdir/etc/falco - patch -i $srcdir/falco.patch - patch -i $srcdir/rules.patch + patch -i --no-backup-if-mismatch $srcdir/falco.patch + patch -i --no-backup-if-mismatch $srcdir/rules.patch # We dont build anything on targets so remove sources rm -rf $pkgdir/usr/src @@ -67,8 +65,7 @@ package() { } sha512sums=" -dc648d9b0a625a02320ff0235bbf4f4940e7ba40c684a8a1f972d34f0a3447b4a34e665d7fbc0ee1ec9a014f65f81a304dc76b4ec804fc7b4e448f330b9474af falco-0.35.1.tar.gz -8ff7a677f723f2d4a09808939500ddff81f15b8a62a2e091d8042765d105d30b67f9993d05ef129dfad6c866ea37d608a3ae9bc7e99730995542f8b5181ba594 alpine.patch +a3fef235ab4f3121bd0400827712652530ec417498c44ada8b6bf565f7631d035673b53dad94ea6ae9c854d45202ed71b2771f19e0c92eea3fc3503e5b75b02e falco-0.36.2.tar.gz b152fcf6cd81895efa37797ab7ff1aac7350b5f51f2648aa9e3cce9d5ece55791ddf82c396e9da216293e2379a785a294cc972f28a91162dc5bc88ab09e1ab08 falco.patch -d8f71ca7c6d854a866826b3f2f5630b6f30448f794c4c5a56a9ea656ee03c3645a1cf7663b5e79d3ea63d4fab8bd44f91a80b1752c8239c8310efa08b495f2e2 rules.patch +88e722ddbfe8da1f2341d8da66223271987bf7fab0fb907a343010c2af85f637e2621f42c9973863c33f586a2f823f53984ca7358673fc99596d3dc83669a7f1 rules.patch " diff --git a/kubezero/falco/falco_rules.yaml b/kubezero/falco/falco_rules.yaml index a269f7b..c3738b0 100644 --- a/kubezero/falco/falco_rules.yaml +++ b/kubezero/falco/falco_rules.yaml @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 # # Copyright (C) 2023 The Falco Authors. # @@ -15,9 +16,16 @@ # limitations under the License. # +# Information about rules tags and fields can be found here: https://falco.org/docs/rules/#tags-for-current-falco-ruleset +# The initial item in the `tags` fields reflects the maturity level of the rules introduced upon the proposal https://github.com/falcosecurity/rules/blob/main/proposals/20230605-rules-adoption-management-maturity-framework.md +# `tags` fields also include information about the type of workload inspection (host and/or container), and Mitre Attack killchain phases and Mitre TTP code(s) +# Mitre Attack References: +# [1] https://attack.mitre.org/tactics/enterprise/ +# [2] https://raw.githubusercontent.com/mitre/cti/master/enterprise-attack/enterprise-attack.json + # Starting with version 8, the Falco engine supports exceptions. # However the Falco rules file does not use them by default. -- required_engine_version: 17 +- required_engine_version: 0.26.0 # Currently disabled as read/write are ignored syscalls. The nearly # similar open_write/open_read check for files being opened for @@ -27,21 +35,12 @@ # - macro: read # condition: (syscall.type=read and evt.dir=> and fd.type in (file, directory)) -# Information about rules tags and fields can be found here: https://falco.org/docs/rules/#tags-for-current-falco-ruleset -# `tags` fields also include information about the type of workload inspection, Mitre Attack killchain phases and Mitre TTP code(s) -# Mitre Attack References: -# [1] https://attack.mitre.org/tactics/enterprise/ -# [2] https://raw.githubusercontent.com/mitre/cti/master/enterprise-attack/enterprise-attack.json - - macro: open_write condition: (evt.type in (open,openat,openat2) and evt.is_open_write=true and fd.typechar='f' and fd.num>=0) - macro: open_read condition: (evt.type in (open,openat,openat2) and evt.is_open_read=true and fd.typechar='f' and fd.num>=0) -- macro: open_directory - condition: (evt.type in (open,openat,openat2) and evt.is_open_read=true and fd.typechar='d' and fd.num>=0) - # Failed file open attempts, useful to detect threat actors making mistakes # https://man7.org/linux/man-pages/man3/errno.3.html # evt.res=ENOENT - No such file or directory @@ -49,11 +48,27 @@ - macro: open_file_failed condition: (evt.type in (open,openat,openat2) and fd.typechar='f' and fd.num=-1 and evt.res startswith E) +# This macro `never_true` is used as placeholder for tuning negative logical sub-expressions, for example +# - macro: allowed_ssh_hosts +# condition: (never_true) +# can be used in a rules' expression with double negation `and not allowed_ssh_hosts` which effectively evaluates +# to true and does nothing, the perfect empty template for `logical` cases as opposed to list templates. +# When tuning the rule you can override the macro with something useful, e.g. +# - macro: allowed_ssh_hosts +# condition: (evt.hostname contains xyz) - macro: never_true condition: (evt.num=0) -- macro: always_true - condition: (evt.num>=0) +# This macro `always_true` is the flip side of the macro `never_true` and currently is commented out as +# it is not used. You can use it as placeholder for a positive logical sub-expression tuning template +# macro, e.g. `and custom_procs`, where +# - macro: custom_procs +# condition: (always_true) +# later you can customize, override the macros to something like +# - macro: custom_procs +# condition: (proc.name in (custom1, custom2, custom3)) +# - macro: always_true +# condition: (evt.num>=0) # In some cases, such as dropped system call events, information about # the process name may be missing. For some rules that really depend @@ -62,23 +77,6 @@ - macro: proc_name_exists condition: (proc.name!="") -- macro: rename - condition: (evt.type in (rename, renameat, renameat2)) - -- macro: mkdir - condition: (evt.type in (mkdir, mkdirat)) - -- macro: remove - condition: (evt.type in (rmdir, unlink, unlinkat)) - -- macro: modify - condition: (rename or remove) - -# %evt.arg.flags available for evt.dir=>, but only for umount2 -# %evt.arg.name is path and available for evt.dir=< -# - macro: umount -# condition: (evt.type in (umount, umount2)) - - macro: spawned_process condition: (evt.type in (execve, execveat) and evt.dir=<) @@ -88,78 +86,21 @@ - macro: create_hardlink condition: (evt.type in (link, linkat) and evt.dir=<) -- macro: chmod - condition: (evt.type in (chmod, fchmod, fchmodat) and evt.dir=<) - - macro: kernel_module_load condition: (evt.type in (init_module, finit_module) and evt.dir=<) +- macro: dup + condition: (evt.type in (dup, dup2, dup3)) + # File categories -- macro: bin_dir - condition: (fd.directory in (/bin, /sbin, /usr/bin, /usr/sbin)) - -- macro: bin_dir_mkdir - condition: > - (evt.arg.path startswith /bin/ or - evt.arg.path startswith /sbin/ or - evt.arg.path startswith /usr/bin/ or - evt.arg.path startswith /usr/sbin/) - -- macro: bin_dir_rename - condition: > - (evt.arg.path startswith /bin/ or - evt.arg.path startswith /sbin/ or - evt.arg.path startswith /usr/bin/ or - evt.arg.path startswith /usr/sbin/ or - evt.arg.name startswith /bin/ or - evt.arg.name startswith /sbin/ or - evt.arg.name startswith /usr/bin/ or - evt.arg.name startswith /usr/sbin/ or - evt.arg.oldpath startswith /bin/ or - evt.arg.oldpath startswith /sbin/ or - evt.arg.oldpath startswith /usr/bin/ or - evt.arg.oldpath startswith /usr/sbin/ or - evt.arg.newpath startswith /bin/ or - evt.arg.newpath startswith /sbin/ or - evt.arg.newpath startswith /usr/bin/ or - evt.arg.newpath startswith /usr/sbin/) - - macro: etc_dir condition: (fd.name startswith /etc/) -# This detects writes immediately below / or any write anywhere below /root -- macro: root_dir - condition: (fd.directory=/ or fd.name startswith /root/) - - list: shell_binaries items: [ash, bash, csh, ksh, sh, tcsh, zsh, dash] -- list: ssh_binaries - items: [ - sshd, sftp-server, ssh-agent, - ssh, scp, sftp, - ssh-keygen, ssh-keysign, ssh-keyscan, ssh-add - ] - -- list: shell_mgmt_binaries - items: [add-shell, remove-shell] - - macro: shell_procs - condition: proc.name in (shell_binaries) - -- list: coreutils_binaries - items: [ - truncate, sha1sum, numfmt, fmt, fold, uniq, cut, who, - groups, csplit, sort, expand, printf, printenv, unlink, tee, chcon, stat, - basename, split, nice, "yes", whoami, sha224sum, hostid, users, stdbuf, - base64, unexpand, cksum, od, paste, nproc, pathchk, sha256sum, wc, test, - comm, arch, du, factor, sha512sum, md5sum, tr, runcon, env, dirname, - tsort, join, shuf, install, logname, pinky, nohup, expr, pr, tty, timeout, - tail, "[", seq, sha384sum, nl, head, id, mkfifo, sum, dircolors, ptx, shred, - tac, link, chroot, vdir, chown, touch, ls, dd, uname, "true", pwd, date, - chgrp, chmod, mktemp, cat, mknod, sync, ln, "false", rm, mv, cp, echo, - readlink, sleep, stty, mkdir, df, dir, rmdir, touch - ] + condition: (proc.name in (shell_binaries)) # dpkg -L login | grep bin | xargs ls -ld | grep -v '^d' | awk '{print $9}' | xargs -L 1 basename | tr "\\n" "," - list: login_binaries @@ -186,15 +127,6 @@ newusers, pwck, pwconv, pwunconv, useradd, userdel, usermod, vigr, vipw, unix_chkpwd ] -- list: sysdigcloud_binaries - items: [setup-backend, dragent, sdchecks] - -- list: k8s_binaries - items: [hyperkube, skydns, kube2sky, exechealthz, weave-net, loopback, bridge, openshift-sdn, openshift] - -- list: lxd_binaries - items: [lxd, lxcfs] - - list: http_server_binaries items: [nginx, httpd, httpd-foregroun, lighttpd, apache, apache2] @@ -210,15 +142,8 @@ - list: gitlab_binaries items: [gitlab-shell, gitlab-mon, gitlab-runner-b, git] -- list: interpreted_binaries - items: [lua, node, perl, perl5, perl6, php, python, python2, python3, ruby, tcl] - -- macro: interpreted_procs - condition: > - (proc.name in (interpreted_binaries)) - - macro: server_procs - condition: proc.name in (http_server_binaries, db_server_binaries, docker_binaries, sshd) + condition: (proc.name in (http_server_binaries, db_server_binaries, docker_binaries, sshd)) # The explicit quotes are needed to avoid the - characters being # interpreted by the filter expression. @@ -227,12 +152,6 @@ repoquery, rpmkeys, rpmq, yum-cron, yum-config-mana, yum-debug-dump, abrt-action-sav, rpmdb_stat, microdnf, rhn_check, yumdb] -- list: openscap_rpm_binaries - items: [probe_rpminfo, probe_rpmverify, probe_rpmverifyfile, probe_rpmverifypackage] - -- macro: rpm_procs - condition: (proc.name in (rpm_binaries, openscap_rpm_binaries) or proc.name in (salt-call, salt-minion)) - - list: deb_binaries items: [dpkg, dpkg-preconfigu, dpkg-reconfigur, dpkg-divert, apt, apt-get, aptitude, frontend, preinst, add-apt-reposit, apt-auto-remova, apt-key, @@ -246,45 +165,17 @@ - list: package_mgmt_binaries items: [rpm_binaries, deb_binaries, update-alternat, gem, npm, python_package_managers, sane-utils.post, alternatives, chef-client, apk, snapd] -- macro: package_mgmt_procs - condition: proc.name in (package_mgmt_binaries) - -- macro: package_mgmt_ancestor_procs - condition: proc.pname in (package_mgmt_binaries) or - proc.aname[2] in (package_mgmt_binaries) or - proc.aname[3] in (package_mgmt_binaries) or - proc.aname[4] in (package_mgmt_binaries) - -- macro: coreos_write_ssh_dir - condition: (proc.name=update-ssh-keys and fd.name startswith /home/core/.ssh) - - macro: run_by_package_mgmt_binaries - condition: proc.aname in (package_mgmt_binaries, needrestart) - -- list: ssl_mgmt_binaries - items: [ca-certificates] - -- list: dhcp_binaries - items: [dhclient, dhclient-script, 11-dhclient] + condition: (proc.aname in (package_mgmt_binaries, needrestart)) # A canonical set of processes that run other programs with different # privileges or as a different user. - list: userexec_binaries items: [sudo, su, suexec, critical-stack, dzdo] -- list: known_setuid_binaries - items: [ - sshd, dbus-daemon-lau, ping, ping6, critical-stack-, pmmcli, - filemng, PassengerAgent, bwrap, osdetect, nginxmng, sw-engine-fpm, - start-stop-daem - ] - - list: user_mgmt_binaries items: [login_binaries, passwd_binaries, shadowutils_binaries] -- list: dev_creation_binaries - items: [blkid, rename_device, update_engine, sgdisk] - - list: hids_binaries items: [aide, aide.wrapper, update-aide.con, logcheck, syslog-summary, osqueryd, ossec-syscheckd] @@ -294,9 +185,6 @@ - list: nomachine_binaries items: [nxexec, nxnode.bin, nxserver.bin, nxclient.bin] -- macro: system_procs - condition: proc.name in (coreutils_binaries, user_mgmt_binaries) - - list: mail_binaries items: [ sendmail, sendmail-msp, postfix, procmail, exim4, @@ -319,202 +207,15 @@ - macro: sensitive_files condition: > - fd.name startswith /etc and - (fd.name in (sensitive_file_names) - or fd.directory in (/etc/sudoers.d, /etc/pam.d)) + ((fd.name startswith /etc and fd.name in (sensitive_file_names)) or + fd.directory in (/etc/sudoers.d, /etc/pam.d)) # Indicates that the process is new. Currently detected using time # since process was started, using a threshold of 5 seconds. - macro: proc_is_new - condition: proc.duration <= 5000000000 - -# Network -- macro: inbound - condition: > - (((evt.type in (accept,accept4,listen) and evt.dir=<) or - (evt.type in (recvfrom,recvmsg) and evt.dir=< and - fd.l4proto != tcp and fd.connected=false and fd.name_changed=true)) and - (fd.typechar = 4 or fd.typechar = 6) and - (fd.ip != "0.0.0.0" and fd.net != "127.0.0.0/8") and - (evt.rawres >= 0 or evt.res = EINPROGRESS)) - -# RFC1918 addresses were assigned for private network usage -- list: rfc_1918_addresses - items: ['"10.0.0.0/8"', '"172.16.0.0/12"', '"192.168.0.0/16"'] - -- macro: outbound - condition: > - (((evt.type = connect and evt.dir=<) or - (evt.type in (sendto,sendmsg) and evt.dir=< and - fd.l4proto != tcp and fd.connected=false and fd.name_changed=true)) and - (fd.typechar = 4 or fd.typechar = 6) and - (fd.ip != "0.0.0.0" and fd.net != "127.0.0.0/8" and not fd.snet in (rfc_1918_addresses)) and - (evt.rawres >= 0 or evt.res = EINPROGRESS)) - -# Very similar to inbound/outbound, but combines the tests together -# for efficiency. -- macro: inbound_outbound - condition: > - ((((evt.type in (accept,accept4,listen,connect) and evt.dir=<)) and - (fd.typechar = 4 or fd.typechar = 6)) and - (fd.ip != "0.0.0.0" and fd.net != "127.0.0.0/8") and - (evt.rawres >= 0 or evt.res = EINPROGRESS)) - -- macro: ssh_port - condition: fd.sport=22 - -# In a local/user rules file, you could override this macro to -# enumerate the servers for which ssh connections are allowed. For -# example, you might have a ssh gateway host for which ssh connections -# are allowed. -# -# In the main falco rules file, there isn't any way to know the -# specific hosts for which ssh access is allowed, so this macro just -# repeats ssh_port, which effectively allows ssh from all hosts. In -# the overridden macro, the condition would look something like -# "fd.sip="a.b.c.d" or fd.sip="e.f.g.h" or ..." -- macro: allowed_ssh_hosts - condition: ssh_port - -- rule: Disallowed SSH Connection - desc: Detect any new ssh connection to a host other than those in an allowed group of hosts - condition: (inbound_outbound) and ssh_port and not allowed_ssh_hosts - enabled: false - output: Disallowed SSH Connection (command=%proc.cmdline pid=%proc.pid connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository) - priority: NOTICE - tags: [host, container, network, mitre_command_and_control, mitre_lateral_movement, T1021.004] - -# These rules and supporting macros are more of an example for how to -# use the fd.*ip and fd.*ip.name fields to match connection -# information against ips, netmasks, and complete domain names. -# -# To use this rule, you should enable it and -# populate allowed_{source,destination}_{ipaddrs,networks,domains} with the -# values that make sense for your environment. - -# Note that this can be either individual IPs or netmasks -- list: allowed_outbound_destination_ipaddrs - items: ['"127.0.0.1"', '"8.8.8.8"'] - -- list: allowed_outbound_destination_networks - items: ['"127.0.0.1/8"'] - -- list: allowed_outbound_destination_domains - items: [google.com, www.yahoo.com] - -- rule: Unexpected outbound connection destination - desc: Detect any outbound connection to a destination outside of an allowed set of ips, networks, or domain names - condition: > - outbound and not - ((fd.sip in (allowed_outbound_destination_ipaddrs)) or - (fd.snet in (allowed_outbound_destination_networks)) or - (fd.sip.name in (allowed_outbound_destination_domains))) - enabled: false - output: Disallowed outbound connection destination (command=%proc.cmdline pid=%proc.pid connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository) - priority: NOTICE - tags: [host, container, network, mitre_command_and_control, TA0011] - -- list: allowed_inbound_source_ipaddrs - items: ['"127.0.0.1"'] - -- list: allowed_inbound_source_networks - items: ['"127.0.0.1/8"', '"10.0.0.0/8"'] - -- list: allowed_inbound_source_domains - items: [google.com] - -- rule: Unexpected inbound connection source - desc: Detect any inbound connection from a source outside of an allowed set of ips, networks, or domain names - condition: > - inbound and not - ((fd.cip in (allowed_inbound_source_ipaddrs)) or - (fd.cnet in (allowed_inbound_source_networks)) or - (fd.cip.name in (allowed_inbound_source_domains))) - enabled: false - output: Disallowed inbound connection source (command=%proc.cmdline pid=%proc.pid connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository) - priority: NOTICE - tags: [host, container, network, mitre_command_and_control, TA0011] - -- list: bash_config_filenames - items: [.bashrc, .bash_profile, .bash_history, .bash_login, .bash_logout, .inputrc, .profile] - -- list: bash_config_files - items: [/etc/profile, /etc/bashrc] - -# Covers both csh and tcsh -- list: csh_config_filenames - items: [.cshrc, .login, .logout, .history, .tcshrc, .cshdirs] - -- list: csh_config_files - items: [/etc/csh.cshrc, /etc/csh.login] - -- list: zsh_config_filenames - items: [.zshenv, .zprofile, .zshrc, .zlogin, .zlogout] - -- list: shell_config_filenames - items: [bash_config_filenames, csh_config_filenames, zsh_config_filenames] - -- list: shell_config_files - items: [bash_config_files, csh_config_files] - -- list: shell_config_directories - items: [/etc/zsh] - -- macro: user_known_shell_config_modifiers - condition: (never_true) - -- rule: Modify Shell Configuration File - desc: Detect attempt to modify shell configuration files - condition: > - open_write and - (fd.filename in (shell_config_filenames) or - fd.name in (shell_config_files) or - fd.directory in (shell_config_directories)) - and not proc.name in (shell_binaries) - and not exe_running_docker_save - and not user_known_shell_config_modifiers - output: > - a shell configuration file has been modified (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid pcmdline=%proc.pcmdline file=%fd.name container_id=%container.id image=%container.image.repository) - priority: - WARNING - tags: [host, container, filesystem, mitre_persistence, T1546.004] - -# This rule is not enabled by default, as there are many legitimate -# readers of shell config files. -- rule: Read Shell Configuration File - desc: Detect attempts to read shell configuration files by non-shell programs - condition: > - open_read and - (fd.filename in (shell_config_filenames) or - fd.name in (shell_config_files) or - fd.directory in (shell_config_directories)) and - (not proc.name in (shell_binaries)) - enabled: false - output: > - a shell configuration file was read by a non-shell program (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid file=%fd.name container_id=%container.id image=%container.image.repository) - priority: - WARNING - tags: [host, container, filesystem, mitre_discovery, T1546.004] - -- macro: user_known_cron_jobs - condition: (never_true) - -- rule: Schedule Cron Jobs - desc: Detect cron jobs scheduled - condition: > - ((open_write and fd.name startswith /etc/cron) or - (spawned_process and proc.name = "crontab")) and - not user_known_cron_jobs - enabled: false - output: > - Cron jobs were scheduled to run (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid - file=%fd.name container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag) - priority: - NOTICE - tags: [host, container, filesystem, mitre_persistence, T1053.003] + condition: (proc.duration <= 5000000000) # Use this to test whether the event occurred within a container. - # When displaying container information in the output field, use # %container.info, without any leading term (file=%fd.name # %container.info user=%user.name user_loginuid=%user.loginuid, and not file=%fd.name @@ -524,12 +225,6 @@ - macro: container condition: (container.id != host) -- macro: container_started - condition: > - ((evt.type = container or - (spawned_process and proc.vpid=1)) and - container.image.repository != incomplete) - - macro: interactive condition: > ((proc.aname=sshd and proc.name != sshd) or @@ -546,35 +241,14 @@ - list: sshkit_script_binaries items: [10_etc_sudoers., 10_passwd_group] -- list: plesk_binaries - items: [sw-engine, sw-engine-fpm, sw-engine-kv, filemng, f2bmng] - # System users that should never log into a system. Consider adding your own # service users (e.g. 'apache' or 'mysqld') here. - macro: system_users - condition: user.name in (bin, daemon, games, lp, mail, nobody, sshd, sync, uucp, www-data) - -- macro: httpd_writing_ssl_conf - condition: > - (proc.pname=run-httpd and - (proc.cmdline startswith "sed -ri" or proc.cmdline startswith "sed -i") and - (fd.name startswith /etc/httpd/conf.d/ or fd.name startswith /etc/httpd/conf)) - -- macro: userhelper_writing_etc_security - condition: (proc.name=userhelper and fd.name startswith /etc/security) + condition: (user.name in (bin, daemon, games, lp, mail, nobody, sshd, sync, uucp, www-data)) - macro: ansible_running_python condition: (proc.name in (python, pypy, python3) and proc.cmdline contains ansible) -- macro: python_running_chef - condition: (proc.name=python and (proc.cmdline contains yum-dump.py or proc.cmdline="python /usr/bin/chef-monitor.py")) - -- macro: python_running_denyhosts - condition: > - (proc.name=python and - (proc.cmdline contains /usr/sbin/denyhosts or - proc.cmdline contains /usr/local/bin/denyhosts.py)) - # Qualys seems to run a variety of shell subprocesses, at various # levels. This checks at a few levels without the cost of a full # proc.aname, which traverses the full parent hierarchy. @@ -585,21 +259,6 @@ proc.aname[3]=qualys-cloud-ag or proc.aname[4]=qualys-cloud-ag) -- macro: run_by_sumologic_securefiles - condition: > - ((proc.cmdline="usermod -a -G sumologic_collector" or - proc.cmdline="groupadd sumologic_collector") and - (proc.pname=secureFiles.sh and proc.aname[2]=java)) - -- macro: run_by_yum - condition: ((proc.pname=sh and proc.aname[2]=yum) or - (proc.aname[2]=sh and proc.aname[3]=yum)) - -- macro: run_by_ms_oms - condition: > - (proc.aname[3] startswith omsagent- or - proc.aname[3] startswith scx-) - - macro: run_by_google_accounts_daemon condition: > (proc.aname[1] startswith google_accounts or @@ -612,12 +271,6 @@ proc.aname[2]=chef-client or proc.aname[3]=chef-client or proc.name=chef-client) -- macro: run_by_adclient - condition: (proc.aname[2]=adclient or proc.aname[3]=adclient or proc.aname[4]=adclient) - -- macro: run_by_centrify - condition: (proc.aname[2]=centrify or proc.aname[3]=centrify or proc.aname[4]=centrify) - # Also handles running semi-indirectly via scl - macro: run_by_foreman condition: > @@ -625,40 +278,12 @@ ((proc.pname in (rake, ruby, scl) and proc.aname[5] in (tfm-rake,tfm-ruby)) or (proc.pname=scl and proc.aname[2] in (tfm-rake,tfm-ruby)))) -- macro: java_running_sdjagent - condition: proc.name=java and proc.cmdline contains sdjagent.jar - -- macro: kubelet_running_loopback - condition: (proc.pname=kubelet and proc.name=loopback) - - macro: python_mesos_marathon_scripting condition: (proc.pcmdline startswith "python3 /marathon-lb/marathon_lb.py") - macro: splunk_running_forwarder condition: (proc.pname=splunkd and proc.cmdline startswith "sh -c /opt/splunkforwarder") -- macro: parent_supervise_running_multilog - condition: (proc.name=multilog and proc.pname=supervise) - -- macro: supervise_writing_status - condition: (proc.name in (supervise,svc) and fd.name startswith "/etc/sb/") - -- macro: pki_realm_writing_realms - condition: (proc.cmdline startswith "bash /usr/local/lib/pki/pki-realm" and fd.name startswith /etc/pki/realms) - -- macro: htpasswd_writing_passwd - condition: (proc.name=htpasswd and fd.name=/etc/nginx/.htpasswd) - -- macro: lvprogs_writing_conf - condition: > - (proc.name in (dmeventd,lvcreate,pvscan,lvs) and - (fd.name startswith /etc/lvm/archive or - fd.name startswith /etc/lvm/backup or - fd.name startswith /etc/lvm/cache)) - -- macro: ovsdb_writing_openvswitch - condition: (proc.name=ovsdb-server and fd.directory=/etc/openvswitch) - - macro: perl_running_plesk condition: (proc.cmdline startswith "perl /opt/psa/admin/bin/plesk_agent_manager" or proc.pcmdline startswith "perl /opt/psa/admin/bin/plesk_agent_manager") @@ -679,731 +304,60 @@ (fd.name=/etc/shadow or fd.directory=/etc/pam.d)) -- macro: parent_ucf_writing_conf - condition: (proc.pname=ucf and proc.aname[2]=frontend) - -- macro: consul_template_writing_conf - condition: > - ((proc.name=consul-template and fd.name startswith /etc/haproxy) or - (proc.name=reload.sh and proc.aname[2]=consul-template and fd.name startswith /etc/ssl)) - -- macro: countly_writing_nginx_conf - condition: (proc.cmdline startswith "nodejs /opt/countly/bin" and fd.name startswith /etc/nginx) - -- list: ms_oms_binaries - items: [omi.postinst, omsconfig.posti, scx.postinst, omsadmin.sh, omiagent] - -- macro: ms_oms_writing_conf - condition: > - ((proc.name in (omiagent,omsagent,in_heartbeat_r*,omsadmin.sh,PerformInventor,dsc_host) - or proc.pname in (ms_oms_binaries) - or proc.aname[2] in (ms_oms_binaries)) - and (fd.name startswith /etc/opt/omi or fd.name startswith /etc/opt/microsoft/omsagent)) - -- macro: ms_scx_writing_conf - condition: (proc.name in (GetLinuxOS.sh) and fd.name startswith /etc/opt/microsoft/scx) - -- macro: azure_scripts_writing_conf - condition: (proc.pname startswith "bash /var/lib/waagent/" and fd.name startswith /etc/azure) - -- macro: azure_networkwatcher_writing_conf - condition: (proc.name in (NetworkWatcherA) and fd.name=/etc/init.d/AzureNetworkWatcherAgent) - -- macro: couchdb_writing_conf - condition: (proc.name=beam.smp and proc.cmdline contains couchdb and fd.name startswith /etc/couchdb) - -- macro: update_texmf_writing_conf - condition: (proc.name=update-texmf and fd.name startswith /etc/texmf) - -- macro: slapadd_writing_conf - condition: (proc.name=slapadd and fd.name startswith /etc/ldap) - -- macro: openldap_writing_conf - condition: (proc.pname=run-openldap.sh and fd.name startswith /etc/openldap) - -- macro: ucpagent_writing_conf - condition: (proc.name=apiserver and container.image.repository=docker/ucp-agent and fd.name=/etc/authorization_config.cfg) - -- macro: iscsi_writing_conf - condition: (proc.name=iscsiadm and fd.name startswith /etc/iscsi) - -- macro: istio_writing_conf - condition: (proc.name=pilot-agent and fd.name startswith /etc/istio) - -- macro: symantec_writing_conf - condition: > - ((proc.name=symcfgd and fd.name startswith /etc/symantec) or - (proc.name=navdefutil and fd.name=/etc/symc-defutils.conf)) - -- macro: liveupdate_writing_conf - condition: (proc.cmdline startswith "java LiveUpdate" and fd.name in (/etc/liveupdate.conf, /etc/Product.Catalog.JavaLiveUpdate)) - -- macro: rancher_agent - condition: (proc.name=agent and container.image.repository contains "rancher/agent") - -- macro: rancher_network_manager - condition: (proc.name=rancher-bridge and container.image.repository contains "rancher/network-manager") - -- macro: sosreport_writing_files - condition: > - (proc.name=urlgrabber-ext- and proc.aname[3]=sosreport and - (fd.name startswith /etc/pkt/nssdb or fd.name startswith /etc/pki/nssdb)) - -- macro: pkgmgmt_progs_writing_pki - condition: > - (proc.name=urlgrabber-ext- and proc.pname in (yum, yum-cron, repoquery) and - (fd.name startswith /etc/pkt/nssdb or fd.name startswith /etc/pki/nssdb)) - -- macro: update_ca_trust_writing_pki - condition: (proc.pname=update-ca-trust and proc.name=trust and fd.name startswith /etc/pki) - -- macro: brandbot_writing_os_release - condition: proc.name=brandbot and fd.name=/etc/os-release - -- macro: selinux_writing_conf - condition: (proc.name in (semodule,genhomedircon,sefcontext_comp) and fd.name startswith /etc/selinux) - -- list: veritas_binaries - items: [vxconfigd, sfcache, vxclustadm, vxdctl, vxprint, vxdmpadm, vxdisk, vxdg, vxassist, vxtune] - - macro: veritas_driver_script condition: (proc.cmdline startswith "perl /opt/VRTSsfmh/bin/mh_driver.pl") -- macro: veritas_progs - condition: (proc.name in (veritas_binaries) or veritas_driver_script) - -- macro: veritas_writing_config - condition: (veritas_progs and (fd.name startswith /etc/vx or fd.name startswith /etc/opt/VRTS or fd.name startswith /etc/vom)) - -- macro: nginx_writing_conf - condition: (proc.name in (nginx,nginx-ingress-c,nginx-ingress) and (fd.name startswith /etc/nginx or fd.name startswith /etc/ingress-controller)) - -- macro: nginx_writing_certs - condition: > - (((proc.name=openssl and proc.pname=nginx-launch.sh) or proc.name=nginx-launch.sh) and fd.name startswith /etc/nginx/certs) - -- macro: chef_client_writing_conf - condition: (proc.pcmdline startswith "chef-client /opt/gitlab" and fd.name startswith /etc/gitlab) - -- macro: centrify_writing_krb - condition: (proc.name in (adjoin,addns) and fd.name startswith /etc/krb5) - -- macro: sssd_writing_krb - condition: (proc.name=adcli and proc.aname[2]=sssd and fd.name startswith /etc/krb5) - -- macro: cockpit_writing_conf - condition: > - ((proc.pname=cockpit-kube-la or proc.aname[2]=cockpit-kube-la) - and fd.name startswith /etc/cockpit) - -- macro: ipsec_writing_conf - condition: (proc.name=start-ipsec.sh and fd.directory=/etc/ipsec) - -- macro: exe_running_docker_save - condition: > - proc.name = "exe" - and (proc.cmdline contains "/var/lib/docker" - or proc.cmdline contains "/var/run/docker") - and proc.pname in (dockerd, docker, dockerd-current, docker-current) - -# Ideally we'd have a length check here as well but -# filterchecks don't have operators like len() -- macro: sed_temporary_file - condition: (proc.name=sed and fd.name startswith "/etc/sed") - -- macro: python_running_get_pip - condition: (proc.cmdline startswith "python get-pip.py") - -- macro: python_running_ms_oms - condition: (proc.cmdline startswith "python /var/lib/waagent/") - -- macro: gugent_writing_guestagent_log - condition: (proc.name=gugent and fd.name=GuestAgent.log) - -- macro: dse_writing_tmp - condition: (proc.name=dse-entrypoint and fd.name=/root/tmp__) - -- macro: zap_writing_state - condition: (proc.name=java and proc.cmdline contains "jar /zap" and fd.name startswith /root/.ZAP) - -- macro: airflow_writing_state - condition: (proc.name=airflow and fd.name startswith /root/airflow) - -- macro: rpm_writing_root_rpmdb - condition: (proc.name=rpm and fd.directory=/root/.rpmdb) - -- macro: maven_writing_groovy - condition: (proc.name=java and proc.cmdline contains "classpath /usr/local/apache-maven" and fd.name startswith /root/.groovy) - -- macro: chef_writing_conf - condition: (proc.name=chef-client and fd.name startswith /root/.chef) - -- macro: kubectl_writing_state - condition: (proc.name in (kubectl,oc) and fd.name startswith /root/.kube) - -- macro: java_running_cassandra - condition: (proc.name=java and proc.cmdline contains "cassandra.jar") - -- macro: cassandra_writing_state - condition: (java_running_cassandra and fd.directory=/root/.cassandra) - -# Istio -- macro: galley_writing_state - condition: (proc.name=galley and fd.name in (known_istio_files)) - -- list: known_istio_files - items: [/healthready, /healthliveness] - -- macro: calico_writing_state - condition: (proc.name=kube-controller and fd.name startswith /status.json and k8s.pod.name startswith calico) - -- macro: calico_writing_envvars - condition: (proc.name=start_runit and fd.name startswith "/etc/envvars" and container.image.repository endswith "calico/node") - -- list: repository_files - items: [sources.list] - -- list: repository_directories - items: [/etc/apt/sources.list.d, /etc/yum.repos.d, /etc/apt] - -- macro: access_repositories - condition: (fd.directory in (repository_directories) or - (fd.name pmatch (repository_directories) and - fd.filename in (repository_files))) - -- macro: modify_repositories - condition: (evt.arg.newpath pmatch (repository_directories)) - -- macro: user_known_update_package_registry - condition: (never_true) - -- rule: Update Package Repository - desc: Detect package repositories get updated - condition: > - ((open_write and access_repositories) or (modify and modify_repositories)) - and not package_mgmt_procs - and not package_mgmt_ancestor_procs - and not exe_running_docker_save - and not user_known_update_package_registry - output: > - Repository files get updated (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid pcmdline=%proc.pcmdline file=%fd.name newpath=%evt.arg.newpath container_id=%container.id image=%container.image.repository) - priority: - NOTICE - tags: [host, container, filesystem, mitre_persistence, T1072] - -# Users should overwrite this macro to specify conditions under which a -# write under the binary dir is ignored. For example, it may be okay to -# install a binary in the context of a ci/cd build. -- macro: user_known_write_below_binary_dir_activities - condition: (never_true) - -- rule: Write below binary dir - desc: an attempt to write to any file below a set of binary directories - condition: > - bin_dir and evt.dir = < and open_write - and not package_mgmt_procs - and not exe_running_docker_save - and not python_running_get_pip - and not python_running_ms_oms - and not user_known_write_below_binary_dir_activities - output: > - File below a known binary directory opened for writing (user=%user.name user_loginuid=%user.loginuid - command=%proc.cmdline pid=%proc.pid file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository) - priority: ERROR - tags: [host, container, filesystem, mitre_persistence, T1543] - -# If you'd like to generally monitor a wider set of directories on top -# of the ones covered by the rule Write below binary dir, you can use -# the following rule and lists. -- list: monitored_directories - items: [/boot, /lib, /lib64, /usr/lib, /usr/local/lib, /usr/local/sbin, /usr/local/bin, /root/.ssh] - - macro: user_ssh_directory condition: (fd.name contains '/.ssh/' and fd.name glob '/home/*/.ssh/*') - macro: directory_traversal condition: (fd.nameraw contains '../' and fd.nameraw glob '*../*../*') -# google_accounts_(daemon) -- macro: google_accounts_daemon_writing_ssh - condition: (proc.name=google_accounts and user_ssh_directory) - -- macro: cloud_init_writing_ssh - condition: (proc.name=cloud-init and user_ssh_directory) - -- macro: mkinitramfs_writing_boot - condition: (proc.pname in (mkinitramfs, update-initramf) and fd.directory=/boot) - -- macro: monitored_dir - condition: > - (fd.directory in (monitored_directories) - or user_ssh_directory) - and not mkinitramfs_writing_boot - -# Add conditions to this macro (probably in a separate file, -# overwriting this macro) to allow for specific combinations of -# programs writing below monitored directories. -# -# Its default value is an expression that always is false, which -# becomes true when the "not ..." in the rule is applied. -- macro: user_known_write_monitored_dir_conditions - condition: (never_true) - -- rule: Write below monitored dir - desc: an attempt to write to any file below a set of monitored directories - condition: > - evt.dir = < and open_write and monitored_dir - and not package_mgmt_procs - and not coreos_write_ssh_dir - and not exe_running_docker_save - and not python_running_get_pip - and not python_running_ms_oms - and not google_accounts_daemon_writing_ssh - and not cloud_init_writing_ssh - and not user_known_write_monitored_dir_conditions - output: > - File below a monitored directory opened for writing (user=%user.name user_loginuid=%user.loginuid - command=%proc.cmdline pid=%proc.pid file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository) - priority: ERROR - tags: [host, container, filesystem, mitre_persistence, T1543] - # ****************************************************************************** # * "Directory traversal monitored file read" requires FALCO_ENGINE_VERSION 13 * # ****************************************************************************** - - rule: Directory traversal monitored file read desc: > - Web applications can be vulnerable to directory traversal attacks that allow accessing files outside of the web app's root directory (e.g. Arbitrary File Read bugs). - System directories like /etc are typically accessed via absolute paths. Access patterns outside of this (here path traversal) can be regarded as suspicious. - This rule includes failed file open attempts. - condition: (open_read or open_file_failed) and (etc_dir or user_ssh_directory or fd.name startswith /root/.ssh or fd.name contains "id_rsa") and directory_traversal and not proc.pname in (shell_binaries) + Web applications can be vulnerable to directory traversal attacks that allow accessing files outside of the web app's root directory + (e.g. Arbitrary File Read bugs). System directories like /etc are typically accessed via absolute paths. Access patterns outside of this + (here path traversal) can be regarded as suspicious. This rule includes failed file open attempts. + condition: > + (open_read or open_file_failed) + and (etc_dir or user_ssh_directory or + fd.name startswith /root/.ssh or + fd.name contains "id_rsa") + and directory_traversal + and not proc.pname in (shell_binaries) enabled: true - output: > - Read monitored file via directory traversal (username=%user.name useruid=%user.uid user_loginuid=%user.loginuid program=%proc.name exe=%proc.exepath - command=%proc.cmdline pid=%proc.pid parent=%proc.pname file=%fd.name fileraw=%fd.nameraw parent=%proc.pname - gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository returncode=%evt.res cwd=%proc.cwd) + output: Read monitored file via directory traversal (file=%fd.name fileraw=%fd.nameraw gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] 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 %container.info) priority: WARNING - tags: [host, container, filesystem, mitre_discovery, mitre_exfiltration, mitre_credential_access, T1555, T1212, T1020, T1552, T1083] - -# The rule below is disabled by default as many system management tools -# like ansible, etc can read these files/paths. Enable it using this macro. -- macro: user_known_read_ssh_information_activities - condition: (never_true) - -- rule: Read ssh information - desc: Any attempt to read files below ssh directories by non-ssh programs - condition: > - ((open_read or open_directory) and - (user_ssh_directory or fd.name startswith /root/.ssh) and - not user_known_read_ssh_information_activities and - not proc.name in (ssh_binaries)) - enabled: false - output: > - ssh-related file/directory read by non-ssh program (user=%user.name user_loginuid=%user.loginuid - command=%proc.cmdline pid=%proc.pid file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline container_id=%container.id image=%container.image.repository) - priority: ERROR - tags: [host, container, filesystem, mitre_discovery, T1005] - -- list: safe_etc_dirs - items: [/etc/cassandra, /etc/ssl/certs/java, /etc/logstash, /etc/nginx/conf.d, /etc/container_environment, /etc/hrmconfig, /etc/fluent/configs.d. /etc/alertmanager] - -- macro: fluentd_writing_conf_files - condition: (proc.name=start-fluentd and fd.name in (/etc/fluent/fluent.conf, /etc/td-agent/td-agent.conf)) - -- macro: qualys_writing_conf_files - condition: (proc.name=qualys-cloud-ag and fd.name=/etc/qualys/cloud-agent/qagent-log.conf) - -- macro: git_writing_nssdb - condition: (proc.name=git-remote-http and fd.directory=/etc/pki/nssdb) - -- macro: plesk_writing_keys - condition: (proc.name in (plesk_binaries) and fd.name startswith /etc/sw/keys) - -- macro: plesk_install_writing_apache_conf - condition: (proc.cmdline startswith "bash -hB /usr/lib/plesk-9.0/services/webserver.apache configure" - and fd.name="/etc/apache2/apache2.conf.tmp") - -- macro: plesk_running_mktemp - condition: (proc.name=mktemp and proc.aname[3] in (plesk_binaries)) - -- macro: networkmanager_writing_resolv_conf - condition: proc.aname[2]=nm-dispatcher and fd.name=/etc/resolv.conf - -- macro: add_shell_writing_shells_tmp - condition: (proc.name=add-shell and fd.name=/etc/shells.tmp) - -- macro: duply_writing_exclude_files - condition: (proc.name=touch and proc.pcmdline startswith "bash /usr/bin/duply" and fd.name startswith "/etc/duply") - -- macro: xmlcatalog_writing_files - condition: (proc.name=update-xmlcatal and fd.directory=/etc/xml) - -- macro: datadog_writing_conf - condition: ((proc.cmdline startswith "python /opt/datadog-agent" or - proc.cmdline startswith "entrypoint.sh /entrypoint.sh datadog start" or - proc.cmdline startswith "agent.py /opt/datadog-agent") - and fd.name startswith "/etc/dd-agent") - -- macro: rancher_writing_conf - condition: ((proc.name in (healthcheck, lb-controller, rancher-dns)) and - (container.image.repository contains "rancher/healthcheck" or - container.image.repository contains "rancher/lb-service-haproxy" or - container.image.repository contains "rancher/dns") and - (fd.name startswith "/etc/haproxy" or fd.name startswith "/etc/rancher-dns")) - -- macro: rancher_writing_root - condition: (proc.name=rancher-metadat and - (container.image.repository contains "rancher/metadata" or container.image.repository contains "rancher/lb-service-haproxy") and - fd.name startswith "/answers.json") - -- macro: checkpoint_writing_state - condition: (proc.name=checkpoint and - container.image.repository contains "coreos/pod-checkpointer" and - fd.name startswith "/etc/kubernetes") - -- macro: jboss_in_container_writing_passwd - condition: > - ((proc.cmdline="run-java.sh /opt/jboss/container/java/run/run-java.sh" - or proc.cmdline="run-java.sh /opt/run-java/run-java.sh") - and container - and fd.name=/etc/passwd) - -- macro: curl_writing_pki_db - condition: (proc.name=curl and fd.directory=/etc/pki/nssdb) - -- macro: haproxy_writing_conf - condition: ((proc.name in (update-haproxy-,haproxy_reload.) or proc.pname in (update-haproxy-,haproxy_reload,haproxy_reload.)) - and (fd.name=/etc/openvpn/client.map or fd.name startswith /etc/haproxy)) - -- macro: java_writing_conf - condition: (proc.name=java and fd.name=/etc/.java/.systemPrefs/.system.lock) - -- macro: rabbitmq_writing_conf - condition: (proc.name=rabbitmq-server and fd.directory=/etc/rabbitmq) - -- macro: rook_writing_conf - condition: (proc.name=toolbox.sh and container.image.repository=rook/toolbox - and fd.directory=/etc/ceph) - -- macro: httpd_writing_conf_logs - condition: (proc.name=httpd and fd.name startswith /etc/httpd/) - -- macro: mysql_writing_conf - condition: > - ((proc.name in (start-mysql.sh, run-mysqld) or proc.pname=start-mysql.sh) and - (fd.name startswith /etc/mysql or fd.directory=/etc/my.cnf.d)) - -- macro: redis_writing_conf - condition: > - (proc.name in (run-redis, redis-launcher.) and (fd.name=/etc/redis.conf or fd.name startswith /etc/redis)) - -- macro: openvpn_writing_conf - condition: (proc.name in (openvpn,openvpn-entrypo) and fd.name startswith /etc/openvpn) - -- macro: php_handlers_writing_conf - condition: (proc.name=php_handlers_co and fd.name=/etc/psa/php_versions.json) - -- macro: sed_writing_temp_file - condition: > - ((proc.aname[3]=cron_start.sh and fd.name startswith /etc/security/sed) or - (proc.name=sed and (fd.name startswith /etc/apt/sources.list.d/sed or - fd.name startswith /etc/apt/sed or - fd.name startswith /etc/apt/apt.conf.d/sed))) - -- macro: cron_start_writing_pam_env - condition: (proc.cmdline="bash /usr/sbin/start-cron" and fd.name=/etc/security/pam_env.conf) - -# In some cases dpkg-reconfigur runs commands that modify /etc. Not -# putting the full set of package management programs yet. -- macro: dpkg_scripting - condition: (proc.aname[2] in (dpkg-reconfigur, dpkg-preconfigu)) - -- macro: ufw_writing_conf - condition: (proc.name=ufw and fd.directory=/etc/ufw) - -- macro: calico_writing_conf - condition: > - (((proc.name = calico-node) or - (container.image.repository=gcr.io/projectcalico-org/node and proc.name in (start_runit, cp)) or - (container.image.repository=gcr.io/projectcalico-org/cni and proc.name=sed)) - and fd.name startswith /etc/calico) - -- macro: prometheus_conf_writing_conf - condition: (proc.name=prometheus-conf and fd.name startswith /etc/prometheus/config_out) - -- macro: openshift_writing_conf - condition: (proc.name=oc and fd.name startswith /etc/origin/node) - -- macro: keepalived_writing_conf - condition: (proc.name in (keepalived, kube-keepalived) and fd.name=/etc/keepalived/keepalived.conf) - -- macro: etcd_manager_updating_dns - condition: (container and proc.name=etcd-manager and fd.name=/etc/hosts) - -- macro: automount_using_mtab - condition: (proc.pname = automount and fd.name startswith /etc/mtab) - -- macro: mcafee_writing_cma_d - condition: (proc.name=macompatsvc and fd.directory=/etc/cma.d) - -- macro: avinetworks_supervisor_writing_ssh - condition: > - (proc.cmdline="se_supervisor.p /opt/avi/scripts/se_supervisor.py -d" and - (fd.name startswith /etc/ssh/known_host_ or - fd.name startswith /etc/ssh/ssh_monitor_config_ or - fd.name startswith /etc/ssh/ssh_config_)) - -- macro: multipath_writing_conf - condition: (proc.name = multipath and fd.name startswith /etc/multipath/) - -# Add conditions to this macro (probably in a separate file, -# overwriting this macro) to allow for specific combinations of -# programs writing below specific directories below -# /etc. fluentd_writing_conf_files is a good example to follow, as it -# specifies both the program doing the writing as well as the specific -# files it is allowed to modify. -# -# In this file, it just takes one of the programs in the base macro -# and repeats it. - -- macro: user_known_write_etc_conditions - condition: proc.name=confd - -# This is a placeholder for user to extend the whitelist for write below etc rule -- macro: user_known_write_below_etc_activities - condition: (never_true) - -- macro: calico_node - condition: (container.image.repository endswith calico/node and proc.name=calico-node) - -- macro: write_etc_common - condition: > - etc_dir and evt.dir = < and open_write - and proc_name_exists - and not proc.name in (passwd_binaries, shadowutils_binaries, sysdigcloud_binaries, - package_mgmt_binaries, ssl_mgmt_binaries, dhcp_binaries, - dev_creation_binaries, shell_mgmt_binaries, - mail_config_binaries, - sshkit_script_binaries, - ldconfig.real, ldconfig, confd, gpg, insserv, - apparmor_parser, update-mime, tzdata.config, tzdata.postinst, - systemd, systemd-machine, systemd-sysuser, - debconf-show, rollerd, bind9.postinst, sv, - gen_resolvconf., update-ca-certi, certbot, runsv, - qualys-cloud-ag, locales.postins, nomachine_binaries, - adclient, certutil, crlutil, pam-auth-update, parallels_insta, - openshift-launc, update-rc.d, puppet, falcoctl) - and not (container and proc.cmdline in ("cp /run/secrets/kubernetes.io/serviceaccount/ca.crt /etc/pki/ca-trust/source/anchors/openshift-ca.crt")) - and not proc.pname in (sysdigcloud_binaries, mail_config_binaries, hddtemp.postins, sshkit_script_binaries, locales.postins, deb_binaries, dhcp_binaries) - and not fd.name pmatch (safe_etc_dirs) - and not fd.name in (/etc/container_environment.sh, /etc/container_environment.json, /etc/motd, /etc/motd.svc) - and not sed_temporary_file - and not exe_running_docker_save - and not ansible_running_python - and not python_running_denyhosts - and not fluentd_writing_conf_files - and not user_known_write_etc_conditions - and not run_by_centrify - and not run_by_adclient - and not qualys_writing_conf_files - and not git_writing_nssdb - and not plesk_writing_keys - and not plesk_install_writing_apache_conf - and not plesk_running_mktemp - and not networkmanager_writing_resolv_conf - and not run_by_chef - and not add_shell_writing_shells_tmp - and not duply_writing_exclude_files - and not xmlcatalog_writing_files - and not parent_supervise_running_multilog - and not supervise_writing_status - and not pki_realm_writing_realms - and not htpasswd_writing_passwd - and not lvprogs_writing_conf - and not ovsdb_writing_openvswitch - and not datadog_writing_conf - and not curl_writing_pki_db - and not haproxy_writing_conf - and not java_writing_conf - and not dpkg_scripting - and not parent_ucf_writing_conf - and not rabbitmq_writing_conf - and not rook_writing_conf - and not php_handlers_writing_conf - and not sed_writing_temp_file - and not cron_start_writing_pam_env - and not httpd_writing_conf_logs - and not mysql_writing_conf - and not openvpn_writing_conf - and not consul_template_writing_conf - and not countly_writing_nginx_conf - and not ms_oms_writing_conf - and not ms_scx_writing_conf - and not azure_scripts_writing_conf - and not azure_networkwatcher_writing_conf - and not couchdb_writing_conf - and not update_texmf_writing_conf - and not slapadd_writing_conf - and not symantec_writing_conf - and not liveupdate_writing_conf - and not sosreport_writing_files - and not selinux_writing_conf - and not veritas_writing_config - and not nginx_writing_conf - and not nginx_writing_certs - and not chef_client_writing_conf - and not centrify_writing_krb - and not sssd_writing_krb - and not cockpit_writing_conf - and not ipsec_writing_conf - and not httpd_writing_ssl_conf - and not userhelper_writing_etc_security - and not pkgmgmt_progs_writing_pki - and not update_ca_trust_writing_pki - and not brandbot_writing_os_release - and not redis_writing_conf - and not openldap_writing_conf - and not ucpagent_writing_conf - and not iscsi_writing_conf - and not istio_writing_conf - and not ufw_writing_conf - and not calico_writing_conf - and not calico_writing_envvars - and not prometheus_conf_writing_conf - and not openshift_writing_conf - and not keepalived_writing_conf - and not rancher_writing_conf - and not checkpoint_writing_state - and not jboss_in_container_writing_passwd - and not etcd_manager_updating_dns - and not user_known_write_below_etc_activities - and not automount_using_mtab - and not mcafee_writing_cma_d - and not avinetworks_supervisor_writing_ssh - and not multipath_writing_conf - and not calico_node - -- rule: Write below etc - desc: an attempt to write to any file below /etc - condition: write_etc_common - output: "File below /etc opened for writing (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid parent=%proc.pname pcmdline=%proc.pcmdline file=%fd.name program=%proc.name gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] container_id=%container.id image=%container.image.repository)" - priority: ERROR - tags: [host, container, filesystem, mitre_persistence, T1098] - -- list: known_root_files - items: [/root/.monit.state, /root/.auth_tokens, /root/.bash_history, /root/.ash_history, /root/.aws/credentials, - /root/.viminfo.tmp, /root/.lesshst, /root/.bzr.log, /root/.gitconfig.lock, /root/.babel.json, /root/.localstack, - /root/.node_repl_history, /root/.mongorc.js, /root/.dbshell, /root/.augeas/history, /root/.rnd, /root/.wget-hsts, /health, /exec.fifo] - -- list: known_root_directories - items: [/root/.oracle_jre_usage, /root/.ssh, /root/.subversion, /root/.nami] - -- macro: known_root_conditions - condition: (fd.name startswith /root/orcexec. - or fd.name startswith /root/.m2 - or fd.name startswith /root/.npm - or fd.name startswith /root/.pki - or fd.name startswith /root/.ivy2 - or fd.name startswith /root/.config/Cypress - or fd.name startswith /root/.config/pulse - or fd.name startswith /root/.config/configstore - or fd.name startswith /root/jenkins/workspace - or fd.name startswith /root/.jenkins - or fd.name startswith /root/.cache - or fd.name startswith /root/.sbt - or fd.name startswith /root/.java - or fd.name startswith /root/.glide - or fd.name startswith /root/.sonar - or fd.name startswith /root/.v8flag - or fd.name startswith /root/infaagent - or fd.name startswith /root/.local/lib/python - or fd.name startswith /root/.pm2 - or fd.name startswith /root/.gnupg - or fd.name startswith /root/.pgpass - or fd.name startswith /root/.theano - or fd.name startswith /root/.gradle - or fd.name startswith /root/.android - or fd.name startswith /root/.ansible - or fd.name startswith /root/.crashlytics - or fd.name startswith /root/.dbus - or fd.name startswith /root/.composer - or fd.name startswith /root/.gconf - or fd.name startswith /root/.nv - or fd.name startswith /root/.local/share/jupyter - or fd.name startswith /root/oradiag_root - or fd.name startswith /root/workspace - or fd.name startswith /root/jvm - or fd.name startswith /root/.node-gyp) - -# Add conditions to this macro (probably in a separate file, -# overwriting this macro) to allow for specific combinations of -# programs writing below specific directories below -# / or /root. -# -# In this file, it just takes one of the condition in the base macro -# and repeats it. -- macro: user_known_write_root_conditions - condition: fd.name=/root/.bash_history - -# This is a placeholder for user to extend the whitelist for write below root rule -- macro: user_known_write_below_root_activities - condition: (never_true) - -- macro: runc_writing_exec_fifo - condition: (proc.cmdline="runc:[1:CHILD] init" and fd.name=/exec.fifo) - -- macro: runc_writing_var_lib_docker - condition: (proc.cmdline="runc:[1:CHILD] init" and evt.arg.filename startswith /var/lib/docker) - -- macro: mysqlsh_writing_state - condition: (proc.name=mysqlsh and fd.directory=/root/.mysqlsh) - -- rule: Write below root - desc: an attempt to write to any file directly below / or /root - condition: > - root_dir and evt.dir = < and open_write - and proc_name_exists - and not fd.name in (known_root_files) - and not fd.directory pmatch (known_root_directories) - and not exe_running_docker_save - and not gugent_writing_guestagent_log - and not dse_writing_tmp - and not zap_writing_state - and not airflow_writing_state - and not rpm_writing_root_rpmdb - and not maven_writing_groovy - and not chef_writing_conf - and not kubectl_writing_state - and not cassandra_writing_state - and not galley_writing_state - and not calico_writing_state - and not rancher_writing_root - and not runc_writing_exec_fifo - and not mysqlsh_writing_state - and not known_root_conditions - and not user_known_write_root_conditions - and not user_known_write_below_root_activities - output: "File below / or /root opened for writing (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid parent=%proc.pname file=%fd.name program=%proc.name container_id=%container.id image=%container.image.repository)" - priority: ERROR - tags: [host, container, filesystem, mitre_persistence, TA0003] + tags: [maturity_stable, host, container, filesystem, mitre_credential_access, T1555] - macro: cmp_cp_by_passwd - condition: proc.name in (cmp, cp) and proc.pname in (passwd, run-parts) + condition: (proc.name in (cmp, cp) and proc.pname in (passwd, run-parts)) - macro: user_known_read_sensitive_files_activities condition: (never_true) - rule: Read sensitive file trusted after startup desc: > - an attempt to read any sensitive file (e.g. files containing user/password/authentication + An attempt to read any sensitive file (e.g. files containing user/password/authentication information) by a trusted program after startup. Trusted programs might read these files - at startup to load initial state, but not afterwards. - condition: sensitive_files and open_read and server_procs and not proc_is_new and proc.name!="sshd" and not user_known_read_sensitive_files_activities - output: > - Sensitive file opened for reading by trusted program after startup (user=%user.name user_loginuid=%user.loginuid - command=%proc.cmdline pid=%proc.pid parent=%proc.pname file=%fd.name parent=%proc.pname gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository) + at startup to load initial state, but not afterwards. Can be customized as needed. + In modern containerized cloud infrastructures, accessing traditional Linux sensitive files + might be less relevant, yet it remains valuable for baseline detections. While we provide additional + rules for SSH or cloud vendor-specific credentials, you can significantly enhance your security + program by crafting custom rules for critical application credentials unique to your environment. + condition: > + open_read + and sensitive_files + and server_procs + and not proc_is_new + and proc.name!="sshd" + and not user_known_read_sensitive_files_activities + output: Sensitive file opened for reading by trusted program after startup (file=%fd.name pcmdline=%proc.pcmdline gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] 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 %container.info) priority: WARNING - tags: [host, container, filesystem, mitre_credential_access, T1555, T1212, T1020, T1552, T1083] + tags: [maturity_stable, host, container, filesystem, mitre_credential_access, T1555] - list: read_sensitive_file_binaries items: [ @@ -1422,7 +376,6 @@ # # In this file, it just takes one of the macros in the base rule # and repeats it. - - macro: user_read_sensitive_file_conditions condition: cmp_cp_by_passwd @@ -1443,10 +396,15 @@ - rule: Read sensitive file untrusted desc: > - an attempt to read any sensitive file (e.g. files containing user/password/authentication - information). Exceptions are made for known trusted programs. + An attempt to read any sensitive file (e.g. files containing user/password/authentication + information). Exceptions are made for known trusted programs. Can be customized as needed. + In modern containerized cloud infrastructures, accessing traditional Linux sensitive files + might be less relevant, yet it remains valuable for baseline detections. While we provide additional + rules for SSH or cloud vendor-specific credentials, you can significantly enhance your security + program by crafting custom rules for critical application credentials unique to your environment. condition: > - sensitive_files and open_read + open_read + and sensitive_files and proc_name_exists and not proc.name in (user_mgmt_binaries, userexec_binaries, package_mgmt_binaries, cron_binaries, read_sensitive_file_binaries, shell_binaries, hids_binaries, @@ -1469,35 +427,9 @@ and not linux_bench_reading_etc_shadow and not user_known_read_sensitive_files_activities and not user_read_sensitive_file_containers - output: > - Sensitive file opened for reading by non-trusted program (user=%user.name user_loginuid=%user.loginuid program=%proc.name - command=%proc.cmdline pid=%proc.pid file=%fd.name parent=%proc.pname gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] container_id=%container.id image=%container.image.repository) + output: Sensitive file opened for reading by non-trusted program (file=%fd.name gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] 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 %container.info) priority: WARNING - tags: [host, container, filesystem, mitre_credential_access, mitre_discovery, T1555, T1212, T1020, T1552, T1083] - -- macro: amazon_linux_running_python_yum - condition: > - (proc.name = python and - proc.pcmdline = "python -m amazon_linux_extras system_motd" and - proc.cmdline startswith "python -c import yum;") - -- macro: user_known_write_rpm_database_activities - condition: (never_true) - -# Only let rpm-related programs write to the rpm database -- rule: Write below rpm database - desc: an attempt to write to the rpm database by any non-rpm related program - condition: > - fd.name startswith /var/lib/rpm and open_write - and not rpm_procs - and not ansible_running_python - and not python_running_chef - and not exe_running_docker_save - and not amazon_linux_running_python_yum - and not user_known_write_rpm_database_activities - output: "Rpm database opened for writing by a non-rpm program (command=%proc.cmdline pid=%proc.pid file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline container_id=%container.id image=%container.image.repository)" - priority: ERROR - tags: [host, container, filesystem, software_mgmt, mitre_persistence, T1072] + tags: [maturity_stable, host, container, filesystem, mitre_credential_access, T1555] - macro: postgres_running_wal_e condition: (proc.pname=postgres and (proc.cmdline startswith "sh -c envdir /etc/wal-e.d/env /usr/local/bin/wal-e" or proc.cmdline startswith "sh -c envdir \"/run/etc/wal-e.d/env\" wal-g wal-push")) @@ -1517,104 +449,13 @@ condition: (proc.aname[2]=rabbitmqctl and proc.cmdline startswith "sh -c ") - macro: run_by_appdynamics - condition: (proc.pname=java and proc.pcmdline startswith "java -jar -Dappdynamics") - -- macro: user_known_db_spawned_processes - condition: (never_true) - -- rule: DB program spawned process - desc: > - a database-server related program spawned a new process other than itself. - This shouldn\'t occur and is a follow on from some SQL injection attacks. - condition: > - proc.pname in (db_server_binaries) - and spawned_process - and not proc.name in (db_server_binaries) - and not postgres_running_wal_e - and not user_known_db_spawned_processes - output: > - Database-related program spawned process other than itself (user=%user.name user_loginuid=%user.loginuid - program=%proc.cmdline pid=%proc.pid parent=%proc.pname container_id=%container.id image=%container.image.repository exe_flags=%evt.arg.flags) - priority: NOTICE - tags: [host, container, process, database, mitre_execution, T1190] - -- macro: user_known_modify_bin_dir_activities - condition: (never_true) - -- rule: Modify binary dirs - desc: an attempt to modify any file below a set of binary directories. - condition: bin_dir_rename and modify and not package_mgmt_procs and not exe_running_docker_save and not user_known_modify_bin_dir_activities - output: > - File below known binary directory renamed/removed (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid - pcmdline=%proc.pcmdline operation=%evt.type file=%fd.name %evt.args container_id=%container.id image=%container.image.repository) - priority: ERROR - tags: [host, container, filesystem, mitre_persistence, T1222.002] - -- macro: user_known_mkdir_bin_dir_activities - condition: (never_true) - -- rule: Mkdir binary dirs - desc: an attempt to create a directory below a set of binary directories. - condition: > - mkdir - and bin_dir_mkdir - and not package_mgmt_procs - and not user_known_mkdir_bin_dir_activities - and not exe_running_docker_save - output: > - Directory below known binary directory created (user=%user.name user_loginuid=%user.loginuid - command=%proc.cmdline pid=%proc.pid directory=%evt.arg.path container_id=%container.id image=%container.image.repository) - priority: ERROR - tags: [host, container, filesystem, mitre_persistence, T1222.002] - -# This list allows for easy additions to the set of commands allowed -# to change thread namespace without having to copy and override the -# entire change thread namespace rule. -- list: user_known_change_thread_namespace_binaries - items: [crio, multus] - -- macro: user_known_change_thread_namespace_activities - condition: (never_true) - -- list: network_plugin_binaries - items: [aws-cni, azure-vnet] - -- macro: weaveworks_scope - condition: (container.image.repository endswith weaveworks/scope and proc.name=scope) - -- rule: Change thread namespace - desc: > - an attempt to change a program/thread\'s namespace (commonly done - as a part of creating a container) by calling setns. - condition: > - evt.type=setns and evt.dir=< - and proc_name_exists - and not (container.id=host and proc.name in (docker_binaries, k8s_binaries, lxd_binaries, nsenter)) - and not proc.name in (sysdigcloud_binaries, sysdig, calico, oci-umount, cilium-cni, network_plugin_binaries) - and not proc.name in (user_known_change_thread_namespace_binaries) - and not proc.name startswith "runc" - and not proc.cmdline startswith "containerd" - and not proc.pname in (sysdigcloud_binaries, hyperkube, kubelet, protokube, dockerd, tini, aws) - and not java_running_sdjagent - and not kubelet_running_loopback - and not rancher_agent - and not rancher_network_manager - and not calico_node - and not weaveworks_scope - and not user_known_change_thread_namespace_activities - enabled: false - output: > - Namespace change (setns) by unexpected program (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid - parent=%proc.pname %container.info container_id=%container.id image=%container.image.repository:%container.image.tag) - priority: NOTICE - tags: [host, container, process, mitre_privilege_escalation, mitre_lateral_movement, T1611] + condition: (proc.pexe endswith java and proc.pcmdline contains " -jar -Dappdynamics") # The binaries in this list and their descendents are *not* allowed # spawn shells. This includes the binaries spawning shells directly as # well as indirectly. For example, apache -> php/perl for # mod_{php,perl} -> some shell is also not allowed, because the shell # has apache as an ancestor. - - list: protected_shell_spawning_binaries items: [ http_server_binaries, db_server_binaries, nosql_server_binaries, mail_binaries, @@ -1622,31 +463,31 @@ ] - macro: parent_java_running_zookeeper - condition: (proc.pname=java and proc.pcmdline contains org.apache.zookeeper.server) + condition: (proc.pexe endswith java and proc.pcmdline contains org.apache.zookeeper.server) - macro: parent_java_running_kafka - condition: (proc.pname=java and proc.pcmdline contains kafka.Kafka) + condition: (proc.pexe endswith java and proc.pcmdline contains kafka.Kafka) - macro: parent_java_running_elasticsearch - condition: (proc.pname=java and proc.pcmdline contains org.elasticsearch.bootstrap.Elasticsearch) + condition: (proc.pexe endswith java and proc.pcmdline contains org.elasticsearch.bootstrap.Elasticsearch) - macro: parent_java_running_activemq - condition: (proc.pname=java and proc.pcmdline contains activemq.jar) + condition: (proc.pexe endswith java and proc.pcmdline contains activemq.jar) - macro: parent_java_running_cassandra - condition: (proc.pname=java and (proc.pcmdline contains "-Dcassandra.config.loader" or proc.pcmdline contains org.apache.cassandra.service.CassandraDaemon)) + condition: (proc.pexe endswith java and (proc.pcmdline contains "-Dcassandra.config.loader" or proc.pcmdline contains org.apache.cassandra.service.CassandraDaemon)) - macro: parent_java_running_jboss_wildfly - condition: (proc.pname=java and proc.pcmdline contains org.jboss) + condition: (proc.pexe endswith java and proc.pcmdline contains org.jboss) - macro: parent_java_running_glassfish - condition: (proc.pname=java and proc.pcmdline contains com.sun.enterprise.glassfish) + condition: (proc.pexe endswith java and proc.pcmdline contains com.sun.enterprise.glassfish) - macro: parent_java_running_hadoop - condition: (proc.pname=java and proc.pcmdline contains org.apache.hadoop) + condition: (proc.pexe endswith java and proc.pcmdline contains org.apache.hadoop) - macro: parent_java_running_datastax - condition: (proc.pname=java and proc.pcmdline contains com.datastax) + condition: (proc.pexe endswith java and proc.pcmdline contains com.datastax) - macro: nginx_starting_nginx condition: (proc.pname=nginx and proc.cmdline contains "/usr/sbin/nginx -c /etc/nginx/nginx.conf") @@ -1693,7 +534,7 @@ # # Like for node, we make this case opt-in. - macro: possibly_parent_java_running_tomcat - condition: (never_true and proc.pname=java and proc.pcmdline contains org.apache.catalina.startup.Bootstrap) + condition: (never_true and proc.pexe endswith java and proc.pcmdline contains org.apache.catalina.startup.Bootstrap) - macro: protected_shell_spawner condition: > @@ -1718,7 +559,16 @@ # (the ./run and ./finish scripts), but the processes runsv can not # spawn shells. - rule: Run shell untrusted - desc: an attempt to spawn a shell below a non-shell application. Specific applications are monitored. + desc: > + An attempt to spawn a shell below a non-shell application. The non-shell applications that are monitored are + defined in the protected_shell_spawner macro, with protected_shell_spawning_binaries being the list you can + easily customize. For Java parent processes, please note that Java often has a custom process name. Therefore, + rely more on proc.exe to define Java applications. This rule can be noisier, as you can see in the exhaustive + existing tuning. However, given it is very behavior-driven and broad, it is universally relevant to catch + general Remote Code Execution (RCE). Allocate time to tune this rule for your use cases and reduce noise. + Tuning suggestions include looking at the duration of the parent process (proc.ppid.duration) to define your + long-running app processes. Checking for newer fields such as proc.vpgid.name and proc.vpgid.exe instead of the + direct parent process being a non-shell application could make the rule more robust. condition: > spawned_process and shell_procs @@ -1749,74 +599,9 @@ and not rabbitmqctl_running_scripts and not run_by_appdynamics and not user_shell_container_exclusions - output: > - Shell spawned by untrusted binary (user=%user.name user_loginuid=%user.loginuid shell=%proc.name parent=%proc.pname - cmdline=%proc.cmdline pid=%proc.pid pcmdline=%proc.pcmdline gparent=%proc.aname[2] ggparent=%proc.aname[3] - aname[4]=%proc.aname[4] aname[5]=%proc.aname[5] aname[6]=%proc.aname[6] aname[7]=%proc.aname[7] container_id=%container.id image=%container.image.repository exe_flags=%evt.arg.flags) - priority: DEBUG - tags: [host, container, process, shell, mitre_execution, T1059.004] - -- macro: allowed_openshift_registry_root - condition: > - (container.image.repository startswith openshift3/ or - container.image.repository startswith registry.redhat.io/openshift3/ or - container.image.repository startswith registry.access.redhat.com/openshift3/) - -# Source: https://docs.openshift.com/enterprise/3.2/install_config/install/disconnected_install.html -- macro: openshift_image - condition: > - (allowed_openshift_registry_root and - (container.image.repository endswith /logging-deployment or - container.image.repository endswith /logging-elasticsearch or - container.image.repository endswith /logging-kibana or - container.image.repository endswith /logging-fluentd or - container.image.repository endswith /logging-auth-proxy or - container.image.repository endswith /metrics-deployer or - container.image.repository endswith /metrics-hawkular-metrics or - container.image.repository endswith /metrics-cassandra or - container.image.repository endswith /metrics-heapster or - container.image.repository endswith /ose-haproxy-router or - container.image.repository endswith /ose-deployer or - container.image.repository endswith /ose-sti-builder or - container.image.repository endswith /ose-docker-builder or - container.image.repository endswith /ose-pod or - container.image.repository endswith /ose-node or - container.image.repository endswith /ose-docker-registry or - container.image.repository endswith /prometheus-node-exporter or - container.image.repository endswith /image-inspector)) - -- list: redhat_io_images_privileged - items: [registry.redhat.io/openshift-logging/fluentd-rhel8, registry.redhat.io/openshift4/ose-csi-node-driver-registrar, registry.redhat.io/openshift4/ose-kubernetes-nmstate-handler-rhel8, registry.redhat.io/openshift4/ose-local-storage-diskmaker] - -- macro: redhat_image - condition: > - (container.image.repository in (redhat_io_images_privileged)) - -# https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html -# official AWS EKS registry list. AWS has different ECR repo per region -- macro: allowed_aws_ecr_registry_root_for_eks - condition: > - (container.image.repository startswith "602401143452.dkr.ecr" or - container.image.repository startswith "877085696533.dkr.ecr" or - container.image.repository startswith "800184023465.dkr.ecr" or - container.image.repository startswith "918309763551.dkr.ecr" or - container.image.repository startswith "961992271922.dkr.ecr" or - container.image.repository startswith "590381155156.dkr.ecr" or - container.image.repository startswith "558608220178.dkr.ecr" or - container.image.repository startswith "151742754352.dkr.ecr" or - container.image.repository startswith "013241004608.dkr.ecr") - - -- macro: aws_eks_core_images - condition: > - (allowed_aws_ecr_registry_root_for_eks and - (container.image.repository endswith ".amazonaws.com/amazon-k8s-cni" or - container.image.repository endswith ".amazonaws.com/eks/kube-proxy")) - - -- macro: aws_eks_image_sensitive_mount - condition: > - (allowed_aws_ecr_registry_root_for_eks and container.image.repository endswith ".amazonaws.com/amazon-k8s-cni") + output: Shell spawned by untrusted binary (parent_exe=%proc.pexe parent_exepath=%proc.pexepath pcmdline=%proc.pcmdline gparent=%proc.aname[2] ggparent=%proc.aname[3] aname[4]=%proc.aname[4] aname[5]=%proc.aname[5] aname[6]=%proc.aname[6] aname[7]=%proc.aname[7] 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 %container.info) + priority: NOTICE + tags: [maturity_stable, host, container, process, shell, mitre_execution, T1059.004] # These images are allowed both to run with --privileged and to mount # sensitive paths from the host filesystem. @@ -1828,20 +613,6 @@ - list: trusted_images items: [] -# Add conditions to this macro (probably in a separate file, -# overwriting this macro) to specify additional containers that are -# trusted and therefore allowed to run privileged *and* with sensitive -# mounts. -# -# Like trusted_images, this is deprecated in favor of -# user_privileged_containers and user_sensitive_mount_containers and -# is only provided for backwards compatibility. -# -# In this file, it just takes one of the images in trusted_containers -# and repeats it. -- macro: user_trusted_containers - condition: (never_true) - - list: sematext_images items: [docker.io/sematext/sematext-agent-docker, docker.io/sematext/agent, docker.io/sematext/logagent, registry.access.redhat.com/sematext/sematext-agent-docker, @@ -1896,110 +667,6 @@ mcr.microsoft.com/oss/kubernetes/kube-proxy ] -- macro: falco_privileged_containers - condition: (openshift_image or - user_trusted_containers or - aws_eks_core_images or - container.image.repository in (trusted_images) or - container.image.repository in (falco_privileged_images) or - container.image.repository startswith istio/proxy_ or - container.image.repository startswith quay.io/sysdig/) - -# Add conditions to this macro (probably in a separate file, -# overwriting this macro) to specify additional containers that are -# allowed to run privileged -# -# In this file, it just takes one of the images in falco_privileged_images -# and repeats it. -- macro: user_privileged_containers - condition: (never_true) - -# These container images are allowed to mount sensitive paths from the -# host filesystem. -- list: falco_sensitive_mount_images - items: [ - falco_containers, - docker.io/sysdig/sysdig, sysdig/sysdig, - gcr.io/google_containers/hyperkube, - gcr.io/google_containers/kube-proxy, docker.io/calico/node, - docker.io/rook/toolbox, docker.io/cloudnativelabs/kube-router, docker.io/consul, - docker.io/datadog/docker-dd-agent, docker.io/datadog/agent, docker.io/docker/ucp-agent, docker.io/gliderlabs/logspout, - docker.io/netdata/netdata, docker.io/google/cadvisor, docker.io/prom/node-exporter, - amazon/amazon-ecs-agent, prom/node-exporter, amazon/cloudwatch-agent - ] - -- macro: falco_sensitive_mount_containers - condition: (user_trusted_containers or - aws_eks_image_sensitive_mount or - container.image.repository in (trusted_images) or - container.image.repository in (falco_sensitive_mount_images) or - container.image.repository startswith quay.io/sysdig/ or - container.image.repository=k8scloudprovider/cinder-csi-plugin) - -# Add conditions to this macro (probably in a separate file, -# overwriting this macro) to specify additional containers that are -# allowed to perform sensitive mounts. -# -# In this file, it just takes one of the images in falco_sensitive_mount_images -# and repeats it. -- macro: user_sensitive_mount_containers - condition: (never_true) - -- rule: Launch Privileged Container - desc: Detect the initial process started in a privileged container. Exceptions are made for known trusted images. - condition: > - container_started and container - and container.privileged=true - and not falco_privileged_containers - and not user_privileged_containers - and not redhat_image - output: Privileged container started (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag) - priority: INFO - tags: [container, cis, mitre_privilege_escalation, mitre_lateral_movement, T1610] - -# These capabilities were used in the past to escape from containers -- macro: excessively_capable_container - condition: > - (thread.cap_permitted contains CAP_SYS_ADMIN - or thread.cap_permitted contains CAP_SYS_MODULE - or thread.cap_permitted contains CAP_SYS_RAWIO - or thread.cap_permitted contains CAP_SYS_PTRACE - or thread.cap_permitted contains CAP_SYS_BOOT - or thread.cap_permitted contains CAP_SYSLOG - or thread.cap_permitted contains CAP_DAC_READ_SEARCH - or thread.cap_permitted contains CAP_NET_ADMIN - or thread.cap_permitted contains CAP_BPF) - -- rule: Launch Excessively Capable Container - desc: Detect container started with a powerful set of capabilities. Exceptions are made for known trusted images. - condition: > - container_started and container - and excessively_capable_container - and not falco_privileged_containers - and not user_privileged_containers - output: Excessively capable container started (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag cap_permitted=%thread.cap_permitted) - priority: INFO - tags: [container, cis, mitre_privilege_escalation, mitre_lateral_movement, T1610] - - -# For now, only considering a full mount of /etc as -# sensitive. Ideally, this would also consider all subdirectories -# below /etc as well, but the globbing mechanism -# doesn't allow exclusions of a full pattern, only single characters. -- macro: sensitive_mount - condition: (container.mount.dest[/proc*] != "N/A" or - container.mount.dest[/var/run/docker.sock] != "N/A" or - container.mount.dest[/var/run/crio/crio.sock] != "N/A" or - container.mount.dest[/run/containerd/containerd.sock] != "N/A" or - container.mount.dest[/var/lib/kubelet] != "N/A" or - container.mount.dest[/var/lib/kubelet/pki] != "N/A" or - container.mount.dest[/] != "N/A" or - container.mount.dest[/home/admin] != "N/A" or - container.mount.dest[/etc] != "N/A" or - container.mount.dest[/etc/kubernetes] != "N/A" or - container.mount.dest[/etc/kubernetes/manifests] != "N/A" or - container.mount.dest[/root*] != "N/A") - # The steps libcontainer performs to set up the root program for a container are: # - clone + exec self to a program runc:[0:PARENT] # - clone a program runc:[1:CHILD] which sets up all the namespaces @@ -2010,41 +677,8 @@ # already exited, or might still be around. So we handle both. # We also let runc:[1:CHILD] count as the parent process, which can occur # when we lose events and lose track of state. - - macro: container_entrypoint - condition: (not proc.pname exists or proc.pname in (runc:[0:PARENT], runc:[1:CHILD], runc, docker-runc, exe, docker-runc-cur)) - -- rule: Launch Sensitive Mount Container - desc: > - Detect the initial process started by a container that has a mount from a sensitive host directory - (i.e. /proc). Exceptions are made for known trusted images. - condition: > - container_started and container - and sensitive_mount - and not falco_sensitive_mount_containers - and not user_sensitive_mount_containers - output: Container with sensitive mount started (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag mounts=%container.mounts) - priority: INFO - tags: [container, cis, mitre_lateral_movement, T1610] - -# In a local/user rules file, you could override this macro to -# explicitly enumerate the container images that you want to run in -# your environment. In this main falco rules file, there isn't any way -# to know all the containers that can run, so any container is -# allowed, by using a filter that is guaranteed to evaluate to true. -# In the overridden macro, the condition would look something like -# (container.image.repository = vendor/container-1 or -# container.image.repository = vendor/container-2 or ...) -- macro: allowed_containers - condition: (container.id exists) - -- rule: Launch Disallowed Container - desc: > - Detect the initial process started by a container that is not in a list of allowed containers. - condition: container_started and container and not allowed_containers - output: Container started and not in allowed list (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag) - priority: WARNING - tags: [container, mitre_lateral_movement, T1610] + condition: (not proc.pname exists or proc.pname in (runc:[0:PARENT], runc:[1:CHILD], runc, docker-runc, exe, docker-runc-cur, containerd-shim, systemd, crio)) - macro: user_known_system_user_login condition: (never_true) @@ -2053,13 +687,24 @@ # - condition: evt.type != switch and user.name = root and proc.name != sshd and interactive # output: "Interactive root (%user.name %proc.name %evt.dir %evt.type %evt.args %fd.name)" # priority: WARNING - - rule: System user interactive - desc: an attempt to run interactive commands by a system (i.e. non-login) user - condition: spawned_process and system_users and interactive and not user_known_system_user_login - output: "System user ran an interactive command (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid container_id=%container.id image=%container.image.repository exe_flags=%evt.arg.flags)" + desc: > + System (e.g. non-login) users spawning new processes. Can add custom service users (e.g. apache or mysqld). + 'Interactive' is defined as new processes as descendants of an ssh session or login process. Consider further tuning + by only looking at processes in a terminal / tty (proc.tty != 0). A newer field proc.is_vpgid_leader could be of help + to distinguish if the process was "directly" executed, for instance, in a tty, or executed as a descendant process in the + same process group, which, for example, is the case when subprocesses are spawned from a script. Consider this rule + as a great template rule to monitor interactive accesses to your systems more broadly. However, such a custom rule would be + unique to your environment. The rule "Terminal shell in container" that fires when using "kubectl exec" is more Kubernetes + relevant, whereas this one could be more interesting for the underlying host. + condition: > + spawned_process + and system_users + and interactive + and not user_known_system_user_login + output: System user ran an interactive command (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 %container.info) priority: INFO - tags: [host, container, users, mitre_execution, T1059] + tags: [maturity_stable, host, container, users, mitre_execution, T1059, NIST_800-53_AC-2] # In some cases, a shell is expected to be run in a container. For example, configuration # management software may do this, which is expected. @@ -2067,23 +712,27 @@ condition: (never_true) - rule: Terminal shell in container - desc: A shell was used as the entrypoint/exec point into a container with an attached terminal. + desc: > + A shell was used as the entrypoint/exec point into a container with an attached terminal. Parent process may have + legitimately already exited and be null (read container_entrypoint macro). Common when using "kubectl exec" in Kubernetes. + Correlate with k8saudit exec logs if possible to find user or serviceaccount token used (fuzzy correlation by namespace and pod name). + Rather than considering it a standalone rule, it may be best used as generic auditing rule while examining other triggered + rules in this container/tty. condition: > - spawned_process and container - and shell_procs and proc.tty != 0 + spawned_process + and container + and shell_procs + and proc.tty != 0 and container_entrypoint and not user_expected_terminal_shell_in_container_conditions - output: > - A shell was spawned in a container with an attached terminal (user=%user.name user_loginuid=%user.loginuid %container.info - shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline pid=%proc.pid terminal=%proc.tty container_id=%container.id image=%container.image.repository exe_flags=%evt.arg.flags) + output: A shell was spawned in a container with an attached terminal (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 %container.info) priority: NOTICE - tags: [container, shell, mitre_execution, T1059] + tags: [maturity_stable, container, shell, mitre_execution, T1059] # For some container types (mesos), there isn't a container image to # work with, and the container name is autogenerated, so there isn't # any stable aspect of the software to work with. In this case, we # fall back to allowing certain command lines. - - list: known_shell_spawn_cmdlines items: [ '"sh -c uname -p 2> /dev/null"', @@ -2136,286 +785,6 @@ - macro: user_shell_container_exclusions condition: (never_true) -- macro: login_doing_dns_lookup - condition: (proc.name=login and fd.l4proto=udp and fd.sport=53) - -# sockfamily ip is to exclude certain processes (like 'groups') that communicate on unix-domain sockets -# systemd can listen on ports to launch things like sshd on demand -- rule: System procs network activity - desc: any network activity performed by system binaries that are not expected to send or receive any network traffic - condition: > - (fd.sockfamily = ip and (system_procs or proc.name in (shell_binaries))) - and (inbound_outbound) - and not proc.name in (known_system_procs_network_activity_binaries) - and not login_doing_dns_lookup - and not user_expected_system_procs_network_activity_conditions - output: > - Known system binary sent/received network traffic - (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid connection=%fd.name container_id=%container.id image=%container.image.repository) - priority: NOTICE - tags: [host, container, network, mitre_exfiltration, T1059, TA0011] - -# This list allows easily whitelisting system proc names that are -# expected to communicate on the network. -- list: known_system_procs_network_activity_binaries - items: [systemd, hostid, id] - -# This macro allows specifying conditions under which a system binary -# is allowed to communicate on the network. For instance, only specific -# proc.cmdline values could be allowed to be more granular in what is -# allowed. -- macro: user_expected_system_procs_network_activity_conditions - condition: (never_true) - -# When filled in, this should look something like: -# (proc.env contains "HTTP_PROXY=http://my.http.proxy.com ") -# The trailing space is intentional so avoid matching on prefixes of -# the actual proxy. -- macro: allowed_ssh_proxy_env - condition: (always_true) - -- list: http_proxy_binaries - items: [curl, wget] - -- macro: http_proxy_procs - condition: (proc.name in (http_proxy_binaries)) - -- rule: Program run with disallowed http proxy env - desc: An attempt to run a program with a disallowed HTTP_PROXY environment variable - condition: > - spawned_process and - http_proxy_procs and - not allowed_ssh_proxy_env and - proc.env icontains HTTP_PROXY - enabled: false - output: > - Program run with disallowed HTTP_PROXY environment variable - (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid env=%proc.env parent=%proc.pname container_id=%container.id image=%container.image.repository exe_flags=%evt.arg.flags) - priority: NOTICE - tags: [host, container, users, mitre_command_and_control, T1090, T1204] - -# In some environments, any attempt by a interpreted program (perl, -# python, ruby, etc) to listen for incoming connections or perform -# outgoing connections might be suspicious. These rules are not -# enabled by default. - -- rule: Interpreted procs inbound network activity - desc: Any inbound network activity performed by any interpreted program (perl, python, ruby, etc.) - condition: > - (inbound and interpreted_procs) - enabled: false - output: > - Interpreted program received/listened for network traffic - (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid connection=%fd.name container_id=%container.id image=%container.image.repository) - priority: NOTICE - tags: [host, container, network, mitre_exfiltration, TA0011] - -- rule: Interpreted procs outbound network activity - desc: Any outbound network activity performed by any interpreted program (perl, python, ruby, etc.) - condition: > - (outbound and interpreted_procs) - enabled: false - output: > - Interpreted program performed outgoing network connection - (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid connection=%fd.name container_id=%container.id image=%container.image.repository) - priority: NOTICE - tags: [host, container, network, mitre_exfiltration, TA0011] - -- list: openvpn_udp_ports - items: [1194, 1197, 1198, 8080, 9201] - -- list: l2tp_udp_ports - items: [500, 1701, 4500, 10000] - -- list: statsd_ports - items: [8125] - -- list: ntp_ports - items: [123] - -# Some applications will connect a udp socket to an address only to -# test connectivity. Assuming the udp connect works, they will follow -# up with a tcp connect that actually sends/receives data. -# -# With that in mind, we listed a few commonly seen ports here to avoid -# some false positives. In addition, we make the main rule opt-in, so -# it's disabled by default. - -- list: test_connect_ports - items: [0, 9, 80, 3306] - -- list: expected_udp_ports - items: [53, openvpn_udp_ports, l2tp_udp_ports, statsd_ports, ntp_ports, test_connect_ports] - -- macro: expected_udp_traffic - condition: fd.port in (expected_udp_ports) - -- rule: Unexpected UDP Traffic - desc: UDP traffic not on port 53 (DNS) or other commonly used ports - condition: (inbound_outbound) and fd.l4proto=udp and not expected_udp_traffic - enabled: false - output: > - Unexpected UDP Traffic Seen - (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid connection=%fd.name proto=%fd.l4proto evt=%evt.type %evt.args container_id=%container.id image=%container.image.repository) - priority: NOTICE - tags: [host, container, network, mitre_exfiltration, TA0011] - -# With the current restriction on system calls handled by falco -# (e.g. excluding read/write/sendto/recvfrom/etc, this rule won't -# trigger). -# - rule: Ssh error in syslog -# desc: any ssh errors (failed logins, disconnects, ...) sent to syslog -# condition: syslog and ssh_error_message and evt.dir = < -# output: "sshd sent error message to syslog (error=%evt.buffer)" -# priority: WARNING - -- macro: somebody_becoming_themselves - condition: ((user.name=nobody and evt.arg.uid=nobody) or - (user.name=www-data and evt.arg.uid=www-data) or - (user.name=_apt and evt.arg.uid=_apt) or - (user.name=postfix and evt.arg.uid=postfix) or - (user.name=pki-agent and evt.arg.uid=pki-agent) or - (user.name=pki-acme and evt.arg.uid=pki-acme) or - (user.name=nfsnobody and evt.arg.uid=nfsnobody) or - (user.name=postgres and evt.arg.uid=postgres)) - -- macro: nrpe_becoming_nagios - condition: (proc.name=nrpe and evt.arg.uid=nagios) - -# In containers, the user name might be for a uid that exists in the -# container but not on the host. (See -# https://github.com/draios/sysdig/issues/954). So in that case, allow -# a setuid. -- macro: known_user_in_container - condition: (container and user.name != "N/A") - -# Add conditions to this macro (probably in a separate file, -# overwriting this macro) to allow for specific combinations of -# programs changing users by calling setuid. -# -# In this file, it just takes one of the condition in the base macro -# and repeats it. -- macro: user_known_non_sudo_setuid_conditions - condition: user.name=root - -# sshd, mail programs attempt to setuid to root even when running as non-root. Excluding here to avoid meaningless FPs -- rule: Non sudo setuid - desc: > - an attempt to change users by calling setuid. sudo/su are excluded. users "root" and "nobody" - suing to itself are also excluded, as setuid calls typically involve dropping privileges. - condition: > - evt.type=setuid and evt.dir=> - and (known_user_in_container or not container) - and not (user.name=root or user.uid=0) - and not somebody_becoming_themselves - and not proc.name in (known_setuid_binaries, userexec_binaries, mail_binaries, docker_binaries, - nomachine_binaries) - and not proc.name startswith "runc:" - and not java_running_sdjagent - and not nrpe_becoming_nagios - and not user_known_non_sudo_setuid_conditions - output: > - Unexpected setuid call by non-sudo, non-root program (user=%user.name user_loginuid=%user.loginuid cur_uid=%user.uid parent=%proc.pname - command=%proc.cmdline pid=%proc.pid uid=%evt.arg.uid container_id=%container.id image=%container.image.repository) - priority: NOTICE - tags: [host, container, users, mitre_privilege_escalation, T1548.001] - -- macro: user_known_user_management_activities - condition: (never_true) - -- macro: chage_list - condition: (proc.name=chage and (proc.cmdline contains "-l" or proc.cmdline contains "--list")) - -- rule: User mgmt binaries - desc: > - activity by any programs that can manage users, passwords, or permissions. sudo and su are excluded. - Activity in containers is also excluded--some containers create custom users on top - of a base linux distribution at startup. - Some innocuous command lines that don't actually change anything are excluded. - condition: > - spawned_process and proc.name in (user_mgmt_binaries) and - not proc.name in (su, sudo, lastlog, nologin, unix_chkpwd) and not container and - not proc.pname in (cron_binaries, systemd, systemd.postins, udev.postinst, run-parts) and - not proc.cmdline startswith "passwd -S" and - not proc.cmdline startswith "useradd -D" and - not proc.cmdline startswith "systemd --version" and - not run_by_qualys and - not run_by_sumologic_securefiles and - not run_by_yum and - not run_by_ms_oms and - not run_by_google_accounts_daemon and - not chage_list and - not user_known_user_management_activities - output: > - User management binary command run outside of container - (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid parent=%proc.pname gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] exe_flags=%evt.arg.flags) - priority: NOTICE - tags: [host, container, users, software_mgmt, mitre_persistence, T1543, T1098] - -- list: allowed_dev_files - items: [ - /dev/null, /dev/stdin, /dev/stdout, /dev/stderr, - /dev/random, /dev/urandom, /dev/console, /dev/kmsg - ] - -- macro: user_known_create_files_below_dev_activities - condition: (never_true) - -# (we may need to add additional checks against false positives, see: -# https://bugs.launchpad.net/ubuntu/+source/rkhunter/+bug/86153) -- rule: Create files below dev - desc: creating any files below /dev other than known programs that manage devices. Some rootkits hide files in /dev. - condition: > - fd.directory = /dev and - (evt.type = creat or (evt.type in (open,openat,openat2) and evt.arg.flags contains O_CREAT)) - and not proc.name in (dev_creation_binaries) - and not fd.name in (allowed_dev_files) - and not fd.name startswith /dev/tty - and not user_known_create_files_below_dev_activities - output: "File created below /dev by untrusted program (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid file=%fd.name container_id=%container.id image=%container.image.repository)" - priority: ERROR - tags: [host, container, filesystem, mitre_persistence, T1543, T1083] - - -# In a local/user rules file, you could override this macro to -# explicitly enumerate the container images that you want to allow -# access to EC2 metadata. In this main falco rules file, there isn't -# any way to know all the containers that should have access, so any -# container is allowed, by repeating the "container" macro. In the -# overridden macro, the condition would look something like -# (container.image.repository = vendor/container-1 or -# container.image.repository = vendor/container-2 or ...) -- macro: ec2_metadata_containers - condition: container - -# On EC2 instances, 169.254.169.254 is a special IP used to fetch -# metadata about the instance. It may be desirable to prevent access -# to this IP from containers. -- rule: Contact EC2 Instance Metadata Service From Container - desc: Detect attempts to contact the EC2 Instance Metadata Service from a container - condition: outbound and fd.sip="169.254.169.254" and container and not ec2_metadata_containers - output: Outbound connection to EC2 instance metadata service (command=%proc.cmdline pid=%proc.pid connection=%fd.name %container.info image=%container.image.repository:%container.image.tag) - priority: NOTICE - enabled: false - tags: [network, aws, container, mitre_discovery, T1565] - - -# This rule is not enabled by default, since this rule is for cloud environment(GCP, AWS and Azure) only. -# You can filter the container that you want to allow access to metadata by overwriting user_known_metadata_access macro. - -- macro: user_known_metadata_access - condition: (k8s.ns.name = "kube-system") - -# On GCP, AWS and Azure, 169.254.169.254 is a special IP used to fetch -# metadata about the instance. The metadata could be used to get credentials by attackers. -- rule: Contact cloud metadata service from container - desc: Detect attempts to contact the Cloud Instance Metadata Service from a container - condition: outbound and fd.sip="169.254.169.254" and container and not user_known_metadata_access - enabled: false - output: Outbound connection to cloud instance metadata service (command=%proc.cmdline pid=%proc.pid connection=%fd.name %container.info image=%container.image.repository:%container.image.tag) - priority: NOTICE - tags: [network, container, mitre_discovery, T1565] - # Containers from IBM Cloud - list: ibm_cloud_containers items: @@ -2453,118 +822,43 @@ condition: (never_true) - rule: Contact K8S API Server From Container - desc: Detect attempts to contact the K8S API Server from a container + desc: > + Detect attempts to communicate with the K8S API Server from a container by non-profiled users. Kubernetes APIs play a + pivotal role in configuring the cluster management lifecycle. Detecting potential unauthorized access to the API server + is of utmost importance. Audit your complete infrastructure and pinpoint any potential machines from which the API server + might be accessible based on your network layout. If Falco can't operate on all these machines, consider analyzing the + Kubernetes audit logs (typically drained from control nodes, and Falco offers a k8saudit plugin) as an additional data + source for detections within the control plane. condition: > - evt.type=connect and evt.dir=< and - (fd.typechar=4 or fd.typechar=6) and - container and - not k8s_containers and - k8s_api_server and - not user_known_contact_k8s_api_server_activities - output: Unexpected connection to K8s API Server from container (command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag connection=%fd.name) + evt.type=connect and evt.dir=< + and (fd.typechar=4 or fd.typechar=6) + and container + and k8s_api_server + and not k8s_containers + and not user_known_contact_k8s_api_server_activities + output: Unexpected connection to K8s API Server from container (connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto 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 %container.info) priority: NOTICE - tags: [network, k8s, container, mitre_discovery, T1565] - -# In a local/user rules file, list the container images that are -# allowed to contact NodePort services from within a container. This -# might cover cases where the K8s infrastructure itself is running -# within a container. -# -# By default, all containers are allowed to contact NodePort services. -- macro: nodeport_containers - condition: container - -- rule: Unexpected K8s NodePort Connection - desc: Detect attempts to use K8s NodePorts from a container - condition: (inbound_outbound) and fd.sport >= 30000 and fd.sport <= 32767 and container and not nodeport_containers - output: Unexpected K8s NodePort Connection (command=%proc.cmdline pid=%proc.pid connection=%fd.name container_id=%container.id image=%container.image.repository) - priority: NOTICE - tags: [network, k8s, container, mitre_persistence, T1205.001] - -- list: network_tool_binaries - items: [nc, ncat, netcat, nmap, dig, tcpdump, tshark, ngrep, telnet, mitmproxy, socat, zmap] - -- macro: network_tool_procs - condition: (proc.name in (network_tool_binaries)) - -# In a local/user rules file, create a condition that matches legitimate uses -# of a package management process inside a container. -# -# For example: -# - macro: user_known_package_manager_in_container -# condition: proc.cmdline="dpkg -l" -- macro: user_known_package_manager_in_container - condition: (never_true) - -# Container is supposed to be immutable. Package management should be done in building the image. -# TODO: Remove k8s.gcr.io reference after 01/Dec/2023 -- macro: pkg_mgmt_in_kube_proxy - condition: > - proc.cmdline startswith "update-alternat" - and (container.image.repository = "registry.k8s.io/kube-proxy" - or container.image.repository = "k8s.gcr.io/kube-proxy") - -- rule: Launch Package Management Process in Container - desc: Package management process ran inside container - condition: > - spawned_process - and container - and user.name != "_apt" - and package_mgmt_procs - and not package_mgmt_ancestor_procs - and not user_known_package_manager_in_container - and not pkg_mgmt_in_kube_proxy - output: > - Package management process launched in container (user=%user.name user_loginuid=%user.loginuid - command=%proc.cmdline pid=%proc.pid container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) - priority: ERROR - tags: [container, process, software_mgmt, mitre_persistence, T1505] + tags: [maturity_stable, container, network, k8s, mitre_discovery, T1565] - rule: Netcat Remote Code Execution in Container - desc: Netcat Program runs inside container that allows remote code execution + desc: > + Netcat Program runs inside container that allows remote code execution and may be utilized + as a part of a variety of reverse shell payload https://github.com/swisskyrepo/PayloadsAllTheThings/. + These programs are of higher relevance as they are commonly installed on UNIX-like operating systems. + Can fire in combination with the "Redirect STDOUT/STDIN to Network Connection in Container" + rule as it utilizes a different evt.type. condition: > - spawned_process and container and - ((proc.name = "nc" and (proc.args contains "-e" or proc.args contains "-c")) or - (proc.name = "ncat" and (proc.args contains "--sh-exec" or proc.args contains "--exec" or proc.args contains "-e " - or proc.args contains "-c " or proc.args contains "--lua-exec")) - ) - output: > - Netcat runs inside container that allows remote code execution (user=%user.name user_loginuid=%user.loginuid - command=%proc.cmdline pid=%proc.pid container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) + spawned_process + and container + and ((proc.name = "nc" and (proc.cmdline contains " -e" or + proc.cmdline contains " -c")) or + (proc.name = "ncat" and (proc.args contains "--sh-exec" or + proc.args contains "--exec" or proc.args contains "-e " or + proc.args contains "-c " or proc.args contains "--lua-exec")) + ) + output: Netcat runs inside container that allows remote code execution (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 %container.info) priority: WARNING - tags: [container, network, process, mitre_execution, T1059] - -- macro: user_known_network_tool_activities - condition: (never_true) - -- rule: Launch Suspicious Network Tool in Container - desc: Detect network tools launched inside container - condition: > - spawned_process and container and network_tool_procs and not user_known_network_tool_activities - output: > - Network tool launched in container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid parent_process=%proc.pname - container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) - priority: NOTICE - tags: [container, network, process, mitre_discovery, mitre_exfiltration, T1595, T1046] - -# This rule is not enabled by default, as there are legitimate use -# cases for these tools on hosts. If you want to enable it, modify the -# following macro. -- macro: consider_network_tools_on_host - condition: (never_true) - -- rule: Launch Suspicious Network Tool on Host - desc: Detect network tools launched on the host - condition: > - spawned_process and - not container and - consider_network_tools_on_host and - network_tool_procs and - not user_known_network_tool_activities - output: > - Network tool launched on host (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid parent_process=%proc.pname exe_flags=%evt.arg.flags) - priority: NOTICE - tags: [host, network, process, mitre_discovery, mitre_exfiltration, T1595, T1046] + tags: [maturity_stable, container, network, process, mitre_execution, T1059] - list: grep_binaries items: [grep, egrep, fgrep] @@ -2591,25 +885,23 @@ - rule: Search Private Keys or Passwords desc: > - Detect grep private keys or passwords activity. + Detect attempts to search for private keys or passwords using the grep or find command. This is often seen with + unsophisticated attackers, as there are many ways to access files using bash built-ins that could go unnoticed. + Regardless, this serves as a solid baseline detection that can be tailored to cover these gaps while maintaining + an acceptable noise level. condition: > - (spawned_process and - ((grep_commands and private_key_or_password) or - (proc.name = "find" and - (proc.args contains "id_rsa" or - proc.args contains "id_dsa" or - proc.args contains "id_ed25519" or - proc.args contains "id_ecdsa" - ) - )) - ) - output: > - Grep private keys or passwords activities found - (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid container_id=%container.id container_name=%container.name - image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) + spawned_process + and ((grep_commands and private_key_or_password) or + (proc.name = "find" and (proc.args contains "id_rsa" or + proc.args contains "id_dsa" or + proc.args contains "id_ed25519" or + proc.args contains "id_ecdsa" + ) + )) + output: Grep private keys or passwords activities found (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 %container.info) priority: WARNING - tags: [host, container, process, filesystem, mitre_credential_access, T1552.001] + tags: [maturity_stable, host, container, process, filesystem, mitre_credential_access, T1552.001] - list: log_directories items: [/var/log, /dev/log] @@ -2630,19 +922,26 @@ container.image.repository endswith "openshift3/ose-logging-fluentd" or container.image.repository endswith "containernetworking/azure-npm") +- macro: containerd_activities + condition: (proc.name=containerd and (fd.name startswith "/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/" or + fd.name startswith "/var/lib/containerd/tmpmounts/")) + - rule: Clear Log Activities - desc: Detect clearing of critical log files + desc: > + Detect clearing of critical access log files, typically done to erase evidence that could be attributed to an adversary's + actions. To effectively customize and operationalize this detection, check for potentially missing log file destinations + relevant to your environment, and adjust the profiled containers you wish not to be alerted on. condition: > - open_write and - access_log_files and - evt.arg.flags contains "O_TRUNC" and - not trusted_logging_images and - not allowed_clear_log_files - output: > - Log files were tampered (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid file=%fd.name container_id=%container.id image=%container.image.repository) + open_write + and access_log_files + and evt.arg.flags contains "O_TRUNC" + and not containerd_activities + and not trusted_logging_images + and not allowed_clear_log_files + output: Log files were tampered (file=%fd.name 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 %container.info) priority: WARNING - tags: [host, container, filesystem, mitre_defense_evasion, T1070] + tags: [maturity_stable, host, container, filesystem, mitre_defense_evasion, T1070, NIST_800-53_AU-10] - list: data_remove_commands items: [shred, mkfs, mke2fs] @@ -2654,680 +953,140 @@ condition: (never_true) - rule: Remove Bulk Data from Disk - desc: Detect process running to clear bulk data from disk - condition: spawned_process and clear_data_procs and not user_known_remove_data_activities - output: > - Bulk data has been removed from disk (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid file=%fd.name container_id=%container.id image=%container.image.repository exe_flags=%evt.arg.flags) + desc: > + Detect a process running to clear bulk data from disk with the intention to destroy data, possibly interrupting availability + to systems. Profile your environment and use user_known_remove_data_activities to tune this rule. + condition: > + spawned_process + and clear_data_procs + and not user_known_remove_data_activities + output: Bulk data has been removed from disk (file=%fd.name 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 %container.info) priority: WARNING - tags: [host, container, process, filesystem, mitre_persistence, T1485] - -# here `ash_history` will match both `bash_history` and `ash_history` -- macro: modify_shell_history - condition: > - (modify and ( - evt.arg.name endswith "ash_history" or - evt.arg.name endswith "zsh_history" or - evt.arg.name contains "fish_read_history" or - evt.arg.name endswith "fish_history" or - evt.arg.oldpath endswith "ash_history" or - evt.arg.oldpath endswith "zsh_history" or - evt.arg.oldpath contains "fish_read_history" or - evt.arg.oldpath endswith "fish_history" or - evt.arg.path endswith "ash_history" or - evt.arg.path endswith "zsh_history" or - evt.arg.path contains "fish_read_history" or - evt.arg.path endswith "fish_history")) - -# here `ash_history` will match both `bash_history` and `ash_history` -- macro: truncate_shell_history - condition: > - (open_write and ( - fd.name endswith "ash_history" or - fd.name endswith "zsh_history" or - fd.name contains "fish_read_history" or - fd.name endswith "fish_history") and evt.arg.flags contains "O_TRUNC") - -- macro: var_lib_docker_filepath - condition: (evt.arg.name startswith /var/lib/docker or fd.name startswith /var/lib/docker) - -- rule: Delete or rename shell history - desc: Detect shell history deletion - condition: > - (modify_shell_history or truncate_shell_history) and - not var_lib_docker_filepath and - not proc.name in (docker_binaries) - output: > - Shell history had been deleted or renamed (user=%user.name user_loginuid=%user.loginuid type=%evt.type command=%proc.cmdline pid=%proc.pid fd.name=%fd.name name=%evt.arg.name path=%evt.arg.path oldpath=%evt.arg.oldpath %container.info) - priority: - WARNING - tags: [host, container, process, filesystem, mitre_defense_evasion, T1070] - -# This rule is deprecated and will/should never be triggered. Keep it here for backport compatibility. -# Rule Delete or rename shell history is the preferred rule to use now. -- rule: Delete Bash History - desc: Detect bash history deletion - condition: > - ((spawned_process and proc.name in (shred, rm, mv) and proc.args contains "bash_history") or - (open_write and fd.name contains "bash_history" and evt.arg.flags contains "O_TRUNC")) - output: > - Shell history had been deleted or renamed (user=%user.name user_loginuid=%user.loginuid type=%evt.type command=%proc.cmdline pid=%proc.pid fd.name=%fd.name name=%evt.arg.name path=%evt.arg.path oldpath=%evt.arg.oldpath exe_flags=%evt.arg.flags %container.info) - priority: - WARNING - tags: [host, container, process, filesystem, mitre_defense_evasion, T1070] - -- list: user_known_chmod_applications - items: [hyperkube, kubelet, k3s-agent] - -# This macro should be overridden in user rules as needed. This is useful if a given application -# should not be ignored altogether with the user_known_chmod_applications list, but only in -# specific conditions. -- macro: user_known_set_setuid_or_setgid_bit_conditions - condition: (never_true) - -- rule: Set Setuid or Setgid bit - desc: > - When the setuid or setgid bits are set for an application, - this means that the application will run with the privileges of the owning user or group respectively. - Detect setuid or setgid bits set via chmod - condition: > - chmod and (evt.arg.mode contains "S_ISUID" or evt.arg.mode contains "S_ISGID") - and not proc.name in (user_known_chmod_applications) - and not exe_running_docker_save - and not user_known_set_setuid_or_setgid_bit_conditions - enabled: false - output: > - Setuid or setgid bit is set via chmod (fd=%evt.arg.fd filename=%evt.arg.filename mode=%evt.arg.mode user=%user.name user_loginuid=%user.loginuid process=%proc.name - command=%proc.cmdline pid=%proc.pid container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag) - priority: - NOTICE - tags: [host, container, process, users, mitre_persistence, T1548.001] - -- list: exclude_hidden_directories - items: [/root/.cassandra] - -# The rule is disabled by default. -- macro: user_known_create_hidden_file_activities - condition: (never_true) - -- rule: Create Hidden Files or Directories - desc: Detect hidden files or directories created - condition: > - ((modify and evt.arg.newpath contains "/.") or - (mkdir and evt.arg.path contains "/.") or - (open_write and evt.arg.flags contains "O_CREAT" and fd.name contains "/." and not fd.name pmatch (exclude_hidden_directories))) and - not user_known_create_hidden_file_activities - and not exe_running_docker_save - enabled: false - output: > - Hidden file or directory created (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid - file=%fd.name newpath=%evt.arg.newpath container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag) - priority: - NOTICE - tags: [host, container, filesystem, mitre_persistence, T1564.001] - -- list: remote_file_copy_binaries - items: [rsync, scp, sftp, dcp] - -- macro: remote_file_copy_procs - condition: (proc.name in (remote_file_copy_binaries)) - -# Users should overwrite this macro to specify conditions under which a -# Custom condition for use of remote file copy tool in container -- macro: user_known_remote_file_copy_activities - condition: (never_true) - -- rule: Launch Remote File Copy Tools in Container - desc: Detect remote file copy tools launched in container - condition: > - spawned_process - and container - and remote_file_copy_procs - and not user_known_remote_file_copy_activities - output: > - Remote file copy tool launched in container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid parent_process=%proc.pname - container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) - priority: NOTICE - tags: [container, network, process, mitre_lateral_movement, mitre_exfiltration, T1020, T1210] + tags: [maturity_stable, host, container, process, filesystem, mitre_impact, T1485] - rule: Create Symlink Over Sensitive Files - desc: Detect symlink created over sensitive files + desc: > + Detect symlinks created over a curated list of sensitive files or subdirectories under /etc/ or + root directories. Can be customized as needed. Refer to further and equivalent guidance within the + rule "Read sensitive file untrusted". condition: > - create_symlink and - (evt.arg.target in (sensitive_file_names) or evt.arg.target in (sensitive_directory_names)) - output: > - Symlinks created over sensitive files (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid target=%evt.arg.target linkpath=%evt.arg.linkpath parent_process=%proc.pname) + create_symlink + and (evt.arg.target in (sensitive_file_names) or evt.arg.target in (sensitive_directory_names)) + output: Symlinks created over sensitive files (target=%evt.arg.target linkpath=%evt.arg.linkpath 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 %container.info) priority: WARNING - tags: [host, container, filesystem, mitre_exfiltration, mitre_credential_access, T1020, T1083, T1212, T1552, T1555] + tags: [maturity_stable, host, container, filesystem, mitre_credential_access, T1555] - rule: Create Hardlink Over Sensitive Files - desc: Detect hardlink created over sensitive files + desc: > + Detect hardlink created over a curated list of sensitive files or subdirectories under /etc/ or + root directories. Can be customized as needed. Refer to further and equivalent guidance within the + rule "Read sensitive file untrusted". condition: > - create_hardlink and - (evt.arg.oldpath in (sensitive_file_names)) - output: > - Hardlinks created over sensitive files (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid target=%evt.arg.oldpath linkpath=%evt.arg.newpath parent_process=%proc.pname) + create_hardlink + and (evt.arg.oldpath in (sensitive_file_names)) + output: Hardlinks created over sensitive files (target=%evt.arg.target linkpath=%evt.arg.linkpath 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 %container.info) priority: WARNING - tags: [host, container, filesystem, mitre_exfiltration, mitre_credential_access, T1020, T1083, T1212, T1552, T1555] - -- list: miner_ports - items: [ - 25, 3333, 3334, 3335, 3336, 3357, 4444, - 5555, 5556, 5588, 5730, 6099, 6666, 7777, - 7778, 8000, 8001, 8008, 8080, 8118, 8333, - 8888, 8899, 9332, 9999, 14433, 14444, - 45560, 45700 - ] - -- list: miner_domains - items: [ - "asia1.ethpool.org","ca.minexmr.com", - "cn.stratum.slushpool.com","de.minexmr.com", - "eth-ar.dwarfpool.com","eth-asia.dwarfpool.com", - "eth-asia1.nanopool.org","eth-au.dwarfpool.com", - "eth-au1.nanopool.org","eth-br.dwarfpool.com", - "eth-cn.dwarfpool.com","eth-cn2.dwarfpool.com", - "eth-eu.dwarfpool.com","eth-eu1.nanopool.org", - "eth-eu2.nanopool.org","eth-hk.dwarfpool.com", - "eth-jp1.nanopool.org","eth-ru.dwarfpool.com", - "eth-ru2.dwarfpool.com","eth-sg.dwarfpool.com", - "eth-us-east1.nanopool.org","eth-us-west1.nanopool.org", - "eth-us.dwarfpool.com","eth-us2.dwarfpool.com", - "eu.stratum.slushpool.com","eu1.ethermine.org", - "eu1.ethpool.org","fr.minexmr.com", - "mine.moneropool.com","mine.xmrpool.net", - "pool.minexmr.com","pool.monero.hashvault.pro", - "pool.supportxmr.com","sg.minexmr.com", - "sg.stratum.slushpool.com","stratum-eth.antpool.com", - "stratum-ltc.antpool.com","stratum-zec.antpool.com", - "stratum.antpool.com","us-east.stratum.slushpool.com", - "us1.ethermine.org","us1.ethpool.org", - "us2.ethermine.org","us2.ethpool.org", - "xmr-asia1.nanopool.org","xmr-au1.nanopool.org", - "xmr-eu1.nanopool.org","xmr-eu2.nanopool.org", - "xmr-jp1.nanopool.org","xmr-us-east1.nanopool.org", - "xmr-us-west1.nanopool.org","xmr.crypto-pool.fr", - "xmr.pool.minergate.com", "rx.unmineable.com", - "ss.antpool.com","dash.antpool.com", - "eth.antpool.com","zec.antpool.com", - "xmc.antpool.com","btm.antpool.com", - "stratum-dash.antpool.com","stratum-xmc.antpool.com", - "stratum-btm.antpool.com" - ] - -- list: https_miner_domains - items: [ - "ca.minexmr.com", - "cn.stratum.slushpool.com", - "de.minexmr.com", - "fr.minexmr.com", - "mine.moneropool.com", - "mine.xmrpool.net", - "pool.minexmr.com", - "sg.minexmr.com", - "stratum-eth.antpool.com", - "stratum-ltc.antpool.com", - "stratum-zec.antpool.com", - "stratum.antpool.com", - "xmr.crypto-pool.fr", - "ss.antpool.com", - "stratum-dash.antpool.com", - "stratum-xmc.antpool.com", - "stratum-btm.antpool.com", - "btm.antpool.com" - ] - -- list: http_miner_domains - items: [ - "ca.minexmr.com", - "de.minexmr.com", - "fr.minexmr.com", - "mine.moneropool.com", - "mine.xmrpool.net", - "pool.minexmr.com", - "sg.minexmr.com", - "xmr.crypto-pool.fr" - ] - -# Add rule based on crypto mining IOCs -- macro: minerpool_https - condition: (fd.sport="443" and fd.sip.name in (https_miner_domains)) - -- macro: minerpool_http - condition: (fd.sport="80" and fd.sip.name in (http_miner_domains)) - -- macro: minerpool_other - condition: (fd.sport in (miner_ports) and fd.sip.name in (miner_domains)) - -- macro: net_miner_pool - condition: (evt.type in (sendto, sendmsg, connect) and evt.dir=< and (fd.net != "127.0.0.0/8" and not fd.snet in (rfc_1918_addresses)) and ((minerpool_http) or (minerpool_https) or (minerpool_other))) - -- macro: trusted_images_query_miner_domain_dns - condition: (container.image.repository in (falco_containers)) - -# The rule is disabled by default. -# Note: falco will send DNS request to resolve miner pool domain which may trigger alerts in your environment. -- rule: Detect outbound connections to common miner pool ports - desc: Miners typically connect to miner pools on common ports. - condition: net_miner_pool and not trusted_images_query_miner_domain_dns - enabled: false - output: Outbound connection to IP/Port flagged by https://cryptoioc.ch (command=%proc.cmdline pid=%proc.pid port=%fd.rport ip=%fd.rip container=%container.info image=%container.image.repository) - priority: CRITICAL - tags: [host, container, network, mitre_execution, T1496] - -- rule: Detect crypto miners using the Stratum protocol - desc: Miners typically specify the mining pool to connect to with a URI that begins with 'stratum+tcp' - condition: spawned_process and (proc.cmdline contains "stratum+tcp" or proc.cmdline contains "stratum2+tcp" or proc.cmdline contains "stratum+ssl" or proc.cmdline contains "stratum2+ssl") - output: Possible miner running (command=%proc.cmdline pid=%proc.pid container=%container.info image=%container.image.repository exe_flags=%evt.arg.flags) - priority: CRITICAL - tags: [host, container, process, mitre_execution, T1496] - -- list: k8s_client_binaries - items: [docker, kubectl, crictl] - -# TODO: Remove k8s.gcr.io reference after 01/Dec/2023 -- list: user_known_k8s_ns_kube_system_images - items: [ - k8s.gcr.io/fluentd-gcp-scaler, - k8s.gcr.io/node-problem-detector/node-problem-detector, - registry.k8s.io/fluentd-gcp-scaler, - registry.k8s.io/node-problem-detector/node-problem-detector - ] - -- list: user_known_k8s_images - items: [ - mcr.microsoft.com/aks/hcp/hcp-tunnel-front - ] - -# Whitelist for known docker client binaries run inside container -# - k8s.gcr.io/fluentd-gcp-scaler / registry.k8s.io/fluentd-gcp-scaler in GCP/GKE -# TODO: Remove k8s.gcr.io reference after 01/Dec/2023 -- macro: user_known_k8s_client_container - condition: > - (k8s.ns.name="kube-system" and container.image.repository in (user_known_k8s_ns_kube_system_images)) or container.image.repository in (user_known_k8s_images) - -- macro: user_known_k8s_client_container_parens - condition: (user_known_k8s_client_container) - -- rule: The docker client is executed in a container - desc: Detect a k8s client tool executed inside a container - condition: spawned_process and container and not user_known_k8s_client_container_parens and proc.name in (k8s_client_binaries) - output: "Docker or kubernetes client executed in container (user=%user.name user_loginuid=%user.loginuid %container.info parent=%proc.pname cmdline=%proc.cmdline pid=%proc.pid image=%container.image.repository:%container.image.tag)" - priority: WARNING - tags: [container, mitre_execution, T1610] + tags: [maturity_stable, host, container, filesystem, mitre_credential_access, T1555] - list: user_known_packet_socket_binaries items: [] - rule: Packet socket created in container - desc: Detect new packet socket at the device driver (OSI Layer 2) level in a container. Packet socket could be used for ARP Spoofing and privilege escalation(CVE-2020-14386) by attacker. - condition: evt.type=socket and evt.arg[0] contains AF_PACKET and container and not proc.name in (user_known_packet_socket_binaries) - output: Packet socket was created in a container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid socket_info=%evt.args container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag) + desc: > + Detect new packet socket at the device driver (OSI Layer 2) level in a container. Packet socket could be used for ARP Spoofing + and privilege escalation (CVE-2020-14386) by an attacker. Noise can be reduced by using the user_known_packet_socket_binaries + template list. + condition: > + evt.type=socket + and container + and evt.arg[0] contains AF_PACKET + and not proc.name in (user_known_packet_socket_binaries) + output: Packet socket was created in a container (socket_info=%evt.args connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto 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 %container.info) priority: NOTICE - tags: [container, network, mitre_discovery, T1046] - -# Namespaces where the rule is enforce -- list: namespace_scope_network_only_subnet - items: [] - -- macro: network_local_subnet - condition: > - fd.rnet in (rfc_1918_addresses) or - fd.ip = "0.0.0.0" or - fd.net = "127.0.0.0/8" - -# # The rule is disabled by default. -# # How to test: -# # Add 'default' to namespace_scope_network_only_subnet -# # Run: -# kubectl run --generator=run-pod/v1 -n default -i --tty busybox --image=busybox --rm -- wget google.com -O /var/google.html -# # Check logs running - -- rule: Network Connection outside Local Subnet - desc: Detect traffic to image outside local subnet. - condition: > - inbound_outbound and - container and - not network_local_subnet and - k8s.ns.name in (namespace_scope_network_only_subnet) - enabled: false - output: > - Network connection outside local subnet - (command=%proc.cmdline pid=%proc.pid connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id - image=%container.image.repository namespace=%k8s.ns.name - fd.rip.name=%fd.rip.name fd.lip.name=%fd.lip.name fd.cip.name=%fd.cip.name fd.sip.name=%fd.sip.name) - priority: WARNING - tags: [container, network, mitre_discovery, T1046] - -- list: allowed_image - items: [] # add image to monitor, i.e.: bitnami/nginx - -- list: authorized_server_binary - items: [] # add binary to allow, i.e.: nginx - -- list: authorized_server_port - items: [] # add port to allow, i.e.: 80 - -# # How to test: -# kubectl run --image=nginx nginx-app --port=80 --env="DOMAIN=cluster" -# kubectl expose deployment nginx-app --port=80 --name=nginx-http --type=LoadBalancer -# # On minikube: -# minikube service nginx-http -# # On general K8s: -# kubectl get services -# kubectl cluster-info -# # Visit the Nginx service and port, should not fire. -# # Change rule to different port, then different process name, and test again that it fires. - -- rule: Outbound or Inbound Traffic not to Authorized Server Process and Port - desc: Detect traffic that is not to authorized server process and port. - condition: > - inbound_outbound and - container and - container.image.repository in (allowed_image) and - not proc.name in (authorized_server_binary) and - not fd.sport in (authorized_server_port) - enabled: false - output: > - Network connection outside authorized port and binary - (command=%proc.cmdline pid=%proc.pid connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id - image=%container.image.repository) - priority: WARNING - tags: [container, network, mitre_discovery, TA0011] + tags: [maturity_stable, container, network, mitre_credential_access, T1557.002] - macro: user_known_stand_streams_redirect_activities condition: (never_true) -- macro: dup - condition: evt.type in (dup, dup2, dup3) - -- rule: Redirect STDOUT/STDIN to Network Connection in Container - desc: Detect redirecting stdout/stdin to network connection in container (potential reverse shell). - condition: dup and container and evt.rawres in (0, 1, 2) and fd.type in ("ipv4", "ipv6") and not user_known_stand_streams_redirect_activities - output: > - Redirect stdout/stdin to network connection (user=%user.name user_loginuid=%user.loginuid %container.info process=%proc.name parent=%proc.pname cmdline=%proc.cmdline pid=%proc.pid terminal=%proc.tty container_id=%container.id image=%container.image.repository fd.name=%fd.name fd.num=%fd.num fd.type=%fd.type fd.sip=%fd.sip) - priority: NOTICE - tags: [container, network, process, mitre_discovery, mitre_execution, T1059] - -# The two Container Drift rules below will fire when a new executable is created in a container. -# There are two ways to create executables - file is created with execution permissions or permissions change of existing file. -# We will use a new filter, is_open_exec, to find all files creations with execution permission, and will trace all chmods in a container. -# The use case we are targeting here is an attempt to execute code that was not shipped as part of a container (drift) - -# an activity that might be malicious or non-compliant. -# Two things to pay attention to: -# 1) In most cases, 'docker cp' will not be identified, but the assumption is that if an attacker gained access to the container runtime daemon, they are already privileged -# 2) Drift rules will be noisy in environments in which containers are built (e.g. docker build) -# These two rules are not enabled by default. - -- macro: user_known_container_drift_activities - condition: (always_true) - -- rule: Container Drift Detected (chmod) - desc: New executable created in a container due to chmod - condition: > - chmod and - container and - not runc_writing_exec_fifo and - not runc_writing_var_lib_docker and - not user_known_container_drift_activities and - evt.rawres>=0 and - ((evt.arg.mode contains "S_IXUSR") or - (evt.arg.mode contains "S_IXGRP") or - (evt.arg.mode contains "S_IXOTH")) - enabled: false - output: Drift detected (chmod), new executable created in a container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode event=%evt.type) - priority: ERROR - tags: [container, process, filesystem, mitre_execution, T1059] - -# **************************************************************************** -# * "Container Drift Detected (open+create)" requires FALCO_ENGINE_VERSION 6 * -# **************************************************************************** -- rule: Container Drift Detected (open+create) - desc: New executable created in a container due to open+create - condition: > - evt.type in (open,openat,openat2,creat) and - evt.is_open_exec=true and - container and - not runc_writing_exec_fifo and - not runc_writing_var_lib_docker and - not user_known_container_drift_activities and - evt.rawres>=0 - enabled: false - output: Drift detected (open+create), new executable created in a container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode event=%evt.type) - priority: ERROR - tags: [container, process, filesystem, mitre_execution, T1059] - -- list: c2_server_ip_list - items: [] - -- list: c2_server_fqdn_list - items: [] - -# For example, you can fetch a list of IP addresses and FQDN on this website: -# https://feodotracker.abuse.ch/downloads/ipblocklist_recommended.json. -# Use Falco HELM chart to update (append) the c2 server lists with your values. -# See an example below. +# As of engine version 20 this rule can be improved by using the fd.types[] +# field so it only triggers once when all three of std{out,err,in} are +# redirected. # -# ```yaml -# # values.yaml Falco HELM chart file -# [...] -# customRules: -# c2-servers-list.yaml: |- -# - list: c2_server_ip_list -# append: true -# items: -# - "'51.178.161.32'" -# - "'46.101.90.205'" -# -# - list: c2_server_fqdn_list -# append: true -# items: -# - "srv-web.ffconsulting.com" -# - "57.ip-142-44-247.net" -# ``` - -- rule: Outbound Connection to C2 Servers - desc: Detect outbound connection to command & control servers thanks to a list of IP addresses & a list of FQDN. - condition: > - outbound and - ((fd.sip in (c2_server_ip_list)) or - (fd.sip.name in (c2_server_fqdn_list))) - output: Outbound connection to C2 server (c2_domain=%fd.sip.name c2_addr=%fd.sip command=%proc.cmdline connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository) - priority: WARNING - enabled: false - tags: [host, container, network, mitre_command_and_control, TA0011] +# - list: ip_sockets +# items: ["ipv4", "ipv6"] +# +# - rule: Redirect STDOUT/STDIN to Network Connection in Container once +# condition: dup and container and evt.rawres in (0, 1, 2) and fd.type in (ip_sockets) and fd.types[0] in (ip_sockets) and fd.types[1] in (ip_sockets) and fd.types[2] in (ip_sockets) and not user_known_stand_streams_redirect_activities +# +# The following rule has not been changed by default as existing users could be +# relying on the rule triggering when any of std{out,err,in} are redirected. +- rule: Redirect STDOUT/STDIN to Network Connection in Container + desc: > + Detect redirection of stdout/stdin to a network connection within a container, achieved by utilizing a + variant of the dup syscall (potential reverse shell or remote code execution + https://github.com/swisskyrepo/PayloadsAllTheThings/). This detection is behavior-based and may generate + noise in the system, and can be adjusted using the user_known_stand_streams_redirect_activities template + macro. Tuning can be performed similarly to existing detections based on process lineage or container images, + and/or it can be limited to interactive tty (tty != 0). + condition: > + dup + and container + and evt.rawres in (0, 1, 2) + and fd.type in ("ipv4", "ipv6") + and not user_known_stand_streams_redirect_activities + output: Redirect stdout/stdin to network connection (gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] fd.sip=%fd.sip connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto 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 %container.info) + priority: NOTICE + tags: [maturity_stable, container, network, process, mitre_execution, T1059] - list: allowed_container_images_loading_kernel_module items: [] -# init_module and finit_module syscalls are available since Falco 0.35.0 -# rule coverage now extends to modprobe usage via init_module logging -# and previous alerting on spawned_process and insmod is now covered -# by finit_module syscall - rule: Linux Kernel Module Injection Detected - desc: Detect kernel module was injected (from container). - condition: kernel_module_load and container + desc: > + Inject Linux Kernel Modules from containers using insmod or modprobe with init_module and finit_module + syscalls, given the precondition of sys_module effective capabilities. Profile the environment and consider + allowed_container_images_loading_kernel_module to reduce noise and account for legitimate cases. + condition: > + kernel_module_load + and container + and thread.cap_effective icontains sys_module and not container.image.repository in (allowed_container_images_loading_kernel_module) - and thread.cap_effective icontains sys_module - output: Linux Kernel Module injection from container detected (user=%user.name uid=%user.uid user_loginuid=%user.loginuid process_name=%proc.name parent_process_name=%proc.pname parent_exepath=%proc.pexepath %proc.aname[2] %proc.aexepath[2] module=%proc.args %container.info image=%container.image.repository:%container.image.tag res=%evt.res syscall=%evt.type) + output: Linux Kernel Module injection from container (parent_exepath=%proc.pexepath gparent=%proc.aname[2] gexepath=%proc.aexepath[2] module=%proc.args res=%evt.res 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 %container.info) priority: WARNING - tags: [host, container, process, mitre_execution, mitre_persistence, TA0002] - -- list: run_as_root_image_list - items: [] - -- macro: user_known_run_as_root_container - condition: (container.image.repository in (run_as_root_image_list)) - -# The rule is disabled by default and should be enabled when non-root container policy has been applied. -# Note the rule will not work as expected when usernamespace is applied, e.g. userns-remap is enabled. -- rule: Container Run as Root User - desc: Detected container running as root user - condition: spawned_process and container and proc.vpid=1 and user.uid=0 and not user_known_run_as_root_container - enabled: false - output: Container launched with root user privilege (uid=%user.uid container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) - priority: INFO - tags: [container, process, users, mitre_execution, T1610] - -# This rule helps detect CVE-2021-3156: -# A privilege escalation to root through heap-based buffer overflow -- rule: Sudo Potential Privilege Escalation - desc: Privilege escalation vulnerability affecting sudo (<= 1.9.5p2). Executing sudo using sudoedit -s or sudoedit -i command with command-line argument that ends with a single backslash character from an unprivileged user it's possible to elevate the user privileges to root. - condition: spawned_process and user.uid != 0 and (proc.name=sudoedit or proc.name = sudo) and (proc.args contains -s or proc.args contains -i or proc.args contains --login) and (proc.args contains "\ " or proc.args endswith \) - output: "Detect Sudo Privilege Escalation Exploit (CVE-2021-3156) (user=%user.name parent=%proc.pname cmdline=%proc.cmdline pid=%proc.pid exe_flags=%evt.arg.flags %container.info)" - priority: CRITICAL - tags: [host, container, filesystem, users, mitre_privilege_escalation, T1548.003] + tags: [maturity_stable, host, container, process, mitre_persistence, TA0003] - rule: Debugfs Launched in Privileged Container - desc: Detect file system debugger debugfs launched inside a privileged container which might lead to container escape. + desc: > + Detect file system debugger debugfs launched inside a privileged container which might lead to container escape. + This rule has a more narrow scope. condition: > - spawned_process and container + spawned_process + and container and container.privileged=true and proc.name=debugfs - output: Debugfs launched started in a privileged container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) + output: Debugfs launched started in a privileged 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 %container.info) priority: WARNING - tags: [container, cis, process, mitre_execution, mitre_lateral_movement, T1611] - -- macro: mount_info - condition: (proc.args="" or proc.args intersects ("-V", "-l", "-h")) - -- macro: known_gke_mount_in_privileged_containers - condition: - (k8s.ns.name = kube-system - and container.image.repository = gke.gcr.io/gcp-compute-persistent-disk-csi-driver) - -- macro: known_aks_mount_in_privileged_containers - condition: - ((k8s.ns.name = kube-system and container.image.repository in (mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi,mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi)) - or (k8s.ns.name = system and container.image.repository = mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver)) - -- macro: user_known_mount_in_privileged_containers - condition: (never_true) - -- rule: Mount Launched in Privileged Container - desc: Detect file system mount happened inside a privileged container which might lead to container escape. - condition: > - spawned_process and container - and container.privileged=true - and proc.name=mount - and not mount_info - and not known_gke_mount_in_privileged_containers - and not known_aks_mount_in_privileged_containers - and not user_known_mount_in_privileged_containers - output: Mount was executed inside a privileged container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) - priority: WARNING - tags: [container, cis, filesystem, mitre_lateral_movement, T1611] - -- list: user_known_userfaultfd_processes - items: [] - -- rule: Unprivileged Delegation of Page Faults Handling to a Userspace Process - desc: Detect a successful unprivileged userfaultfd syscall which might act as an attack primitive to exploit other bugs - condition: > - evt.type = userfaultfd and - user.uid != 0 and - (evt.rawres >= 0 or evt.res != -1) and - not proc.name in (user_known_userfaultfd_processes) - output: An userfaultfd syscall was successfully executed by an unprivileged user (user=%user.name user_loginuid=%user.loginuid process=%proc.name command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag) - priority: CRITICAL - tags: [host, container, process, mitre_defense_evasion, TA0005] - -- list: ingress_remote_file_copy_binaries - items: [wget] - -- macro: ingress_remote_file_copy_procs - condition: (proc.name in (ingress_remote_file_copy_binaries)) - -# Users should overwrite this macro to specify conditions under which a -# Custom condition for use of ingress remote file copy tool in container -- macro: user_known_ingress_remote_file_copy_activities - condition: (never_true) - -- macro: curl_download - condition: proc.name = curl and - (proc.cmdline contains " -o " or - proc.cmdline contains " --output " or - proc.cmdline contains " -O " or - proc.cmdline contains " --remote-name ") - -- rule: Launch Ingress Remote File Copy Tools in Container - desc: Detect ingress remote file copy tools launched in container - condition: > - spawned_process and - container and - (ingress_remote_file_copy_procs or curl_download) and - not user_known_ingress_remote_file_copy_activities - output: > - Ingress remote file copy tool launched in container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid parent_process=%proc.pname - container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) - priority: NOTICE - tags: [container, network, process, mitre_command_and_control, TA0011] - -# This rule helps detect CVE-2021-4034: -# A privilege escalation to root through memory corruption -- rule: Polkit Local Privilege Escalation Vulnerability (CVE-2021-4034) - desc: "This rule detects an attempt to exploit a privilege escalation vulnerability in Polkit's pkexec. By running specially crafted code, a local user can leverage this flaw to gain root privileges on a compromised system" - condition: - spawned_process and user.uid != 0 and proc.name=pkexec and proc.args = '' - output: - "Detect Polkit pkexec Local Privilege Escalation Exploit (CVE-2021-4034) (user=%user.loginname uid=%user.loginuid command=%proc.cmdline pid=%proc.pid args=%proc.args exe_flags=%evt.arg.flags)" - priority: CRITICAL - tags: [host, container, process, users, mitre_privilege_escalation, TA0004] - + tags: [maturity_stable, container, cis, process, mitre_privilege_escalation, T1611] - rule: Detect release_agent File Container Escapes - desc: "This rule detect an attempt to exploit a container escape using release_agent file. By running a container with certains capabilities, a privileged user can modify release_agent file and escape from the container" - condition: - open_write and container and fd.name endswith release_agent and (user.uid=0 or thread.cap_effective contains CAP_DAC_OVERRIDE) and thread.cap_effective contains CAP_SYS_ADMIN - output: - "Detect an attempt to exploit a container escape using release_agent file (user=%user.name user_loginuid=%user.loginuid filename=%fd.name %container.info image=%container.image.repository:%container.image.tag cap_effective=%thread.cap_effective)" - priority: CRITICAL - tags: [container, process, mitre_privilege_escalation, mitre_lateral_movement, T1611] - -# Rule for detecting potential Log4Shell (CVE-2021-44228) exploitation -# Note: Not compatible with Java 17+, which uses read() syscalls -- macro: java_network_read - condition: (evt.type=recvfrom and fd.type in (ipv4, ipv6) and proc.name=java) - -- rule: Java Process Class File Download - desc: Detected Java process downloading a class file which could indicate a successful exploit of the log4shell Log4j vulnerability (CVE-2021-44228) + desc: > + Detect an attempt to exploit a container escape using release_agent file. + By running a container with certains capabilities, a privileged user can modify + release_agent file and escape from the container. condition: > - java_network_read and evt.buffer bcontains cafebabe - output: Java process class file download (user=%user.name user_loginname=%user.loginname user_loginuid=%user.loginuid event=%evt.type connection=%fd.name server_ip=%fd.sip server_port=%fd.sport proto=%fd.l4proto process=%proc.name command=%proc.cmdline pid=%proc.pid parent=%proc.pname buffer=%evt.buffer container_id=%container.id image=%container.image.repository) + open_write + and container + and fd.name endswith release_agent + and (user.uid=0 or thread.cap_effective contains CAP_DAC_OVERRIDE) + and thread.cap_effective contains CAP_SYS_ADMIN + output: Detect an attempt to exploit a container escape using release_agent file (file=%fd.name cap_effective=%thread.cap_effective 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 %container.info) priority: CRITICAL - enabled: false - tags: [host, container, process, mitre_initial_access, T1190] + tags: [maturity_stable, container, process, mitre_privilege_escalation, T1611] - list: docker_binaries items: [docker, dockerd, containerd-shim, "runc:[1:CHILD]", pause, exe, docker-compose, docker-entrypoi, docker-runc-cur, docker-current, dockerd-current] -- macro: docker_procs - condition: proc.name in (docker_binaries) - -- rule: Modify Container Entrypoint - desc: This rule detect an attempt to write on container entrypoint symlink (/proc/self/exe). Possible CVE-2019-5736 Container Breakout exploitation attempt. - condition: > - open_write and container and (fd.name=/proc/self/exe or fd.name startswith /proc/self/fd/) and not docker_procs and not proc.cmdline = "runc:[1:CHILD] init" - enabled: false - output: > - Detect Potential Container Breakout Exploit (CVE-2019-5736) (user=%user.name process=%proc.name file=%fd.name cmdline=%proc.cmdline pid=%proc.pid %container.info) - priority: WARNING - tags: [container, filesystem, mitre_initial_access, T1611] - -- list: known_binaries_to_read_environment_variables_from_proc_files - items: [scsi_id, argoexec] - -- rule: Read environment variable from /proc files - desc: An attempt to read process environment variables from /proc files - condition: > - open_read and container and (fd.name glob /proc/*/environ) - and not proc.name in (known_binaries_to_read_environment_variables_from_proc_files) - output: > - Environment variables were retrieved from /proc files (user=%user.name user_loginuid=%user.loginuid program=%proc.name - command=%proc.cmdline pid=%proc.pid file=%fd.name parent=%proc.pname gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] container_id=%container.id image=%container.image.repository) - priority: WARNING - tags: [container, filesystem, process, mitre_credential_access, mitre_discovery, T1083] - - list: known_ptrace_binaries items: [] @@ -3336,29 +1095,39 @@ - macro: ptrace_attach_or_injection condition: > - evt.type=ptrace and evt.dir=> and + (evt.type=ptrace and evt.dir=> and (evt.arg.request contains PTRACE_POKETEXT or evt.arg.request contains PTRACE_POKEDATA or evt.arg.request contains PTRACE_ATTACH or evt.arg.request contains PTRACE_SEIZE or - evt.arg.request contains PTRACE_SETREGS) + evt.arg.request contains PTRACE_SETREGS)) - rule: PTRACE attached to process - desc: "This rule detects an attempt to inject code into a process using PTRACE." - condition: ptrace_attach_or_injection and proc_name_exists and not known_ptrace_procs - output: > - Detected ptrace PTRACE_ATTACH attempt (proc.cmdline=%proc.cmdline container=%container.info evt.type=%evt.type evt.arg.request=%evt.arg.request proc.pid=%proc.pid proc.cwd=%proc.cwd proc.ppid=%proc.ppid - proc.pcmdline=%proc.pcmdline proc.sid=%proc.sid proc.exepath=%proc.exepath user.uid=%user.uid user.loginuid=%user.loginuid user.loginname=%user.loginname user.name=%user.name group.gid=%group.gid - group.name=%group.name container.id=%container.id container.name=%container.name image=%container.image.repository) + desc: > + Detect an attempt to inject potentially malicious code into a process using PTRACE in order to evade + process-based defenses or elevate privileges. Common anti-patterns are debuggers. Additionally, profiling + your environment via the known_ptrace_procs template macro can reduce noise. + A successful ptrace syscall generates multiple logs at once. + condition: > + ptrace_attach_or_injection + and proc_name_exists + and not known_ptrace_procs + output: Detected ptrace PTRACE_ATTACH attempt (proc_pcmdline=%proc.pcmdline 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 %container.info) priority: WARNING - tags: [host, container, process, mitre_execution, mitre_privilege_escalation, T1055.008] + tags: [maturity_stable, host, container, process, mitre_privilege_escalation, T1055.008] - rule: PTRACE anti-debug attempt - desc: "Detect usage of the PTRACE system call with the PTRACE_TRACEME argument, indicating a program actively attempting to avoid debuggers attaching to the process. This behavior is typically indicative of malware activity." - condition: evt.type=ptrace and evt.dir=> and evt.arg.request contains PTRACE_TRACEME and proc_name_exists - output: Detected potential PTRACE_TRACEME anti-debug attempt (proc.cmdline=%proc.cmdline container=%container.info evt.type=%evt.type evt.arg.request=%evt.arg.request proc.pid=%proc.pid proc.cwd=%proc.cwd proc.ppid=%proc.ppid proc.pcmdline=%proc.pcmdline proc.sid=%proc.sid proc.exepath=%proc.exepath user.uid=%user.uid user.loginuid=%user.loginuid user.loginname=%user.loginname user.name=%user.name group.gid=%group.gid group.name=%group.name container.id=%container.id container.name=%container.name image=%container.image.repository) + desc: > + Detect usage of the PTRACE system call with the PTRACE_TRACEME argument, indicating a program actively attempting + to avoid debuggers attaching to the process. This behavior is typically indicative of malware activity. + Read more about PTRACE in the "PTRACE attached to process" rule. + condition: > + evt.type=ptrace and evt.dir=> + and evt.arg.request contains PTRACE_TRACEME + and proc_name_exists + output: Detected potential PTRACE_TRACEME anti-debug attempt (proc_pcmdline=%proc.pcmdline 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 %container.info) priority: NOTICE - tags: [host, container, process, mitre_defense_evasion, T1622] + tags: [maturity_stable, host, container, process, mitre_defense_evasion, T1622] - macro: private_aws_credentials condition: > @@ -3369,54 +1138,114 @@ proc.args icontains "secretaccesskey") - rule: Find AWS Credentials - desc: Find or grep AWS credentials + desc: > + Detect attempts to search for private keys or passwords using the grep or find command, particularly targeting standard + AWS credential locations. This is often seen with unsophisticated attackers, as there are many ways to access files + using bash built-ins that could go unnoticed. Regardless, this serves as a solid baseline detection that can be tailored + to cover these gaps while maintaining an acceptable noise level. This rule complements the rule "Search Private Keys or Passwords". condition: > - spawned_process and - ((grep_commands and private_aws_credentials) or - (proc.name = "find" and proc.args endswith ".aws/credentials")) - output: Detected AWS credentials search activity (user.name=%user.name user.loginuid=%user.loginuid proc.cmdline=%proc.cmdline container.id=%container.id container_name=%container.name evt.type=%evt.type evt.res=%evt.res proc.pid=%proc.pid proc.cwd=%proc.cwd proc.ppid=%proc.ppid proc.pcmdline=%proc.pcmdline proc.sid=%proc.sid proc.exepath=%proc.exepath user.uid=%user.uid user.loginname=%user.loginname group.gid=%group.gid group.name=%group.name container.name=%container.name image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) + spawned_process + and ((grep_commands and private_aws_credentials) or + (proc.name = "find" and proc.args endswith ".aws/credentials")) + output: Detected AWS credentials search activity (proc_pcmdline=%proc.pcmdline proc_cwd=%proc.cwd group_gid=%group.gid group_name=%group.name user_loginname=%user.loginname 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 %container.info) priority: WARNING - tags: [host, container, mitre_credential_access, process, aws, T1552] + tags: [maturity_stable, host, container, process, aws, mitre_credential_access, T1552] - rule: Execution from /dev/shm - desc: This rule detects file execution from the /dev/shm directory, a common tactic for threat actors to stash their readable+writable+(sometimes)executable files. + desc: > + This rule detects file execution in the /dev/shm directory, a tactic often used by threat actors to store their readable, writable, and + occasionally executable files. /dev/shm acts as a link to the host or other containers, creating vulnerabilities for their compromise + as well. Notably, /dev/shm remains unchanged even after a container restart. Consider this rule alongside the newer + "Drop and execute new binary in container" rule. condition: > - spawned_process and - (proc.exe startswith "/dev/shm/" or - (proc.cwd startswith "/dev/shm/" and proc.exe startswith "./" ) or - (shell_procs and proc.args startswith "-c /dev/shm") or - (shell_procs and proc.args startswith "-i /dev/shm") or - (shell_procs and proc.args startswith "/dev/shm") or - (proc.cwd startswith "/dev/shm/" and proc.args startswith "./" )) and - not container.image.repository in (falco_privileged_images, trusted_images) - output: "File execution detected from /dev/shm (proc.cmdline=%proc.cmdline connection=%fd.name user.name=%user.name user.loginuid=%user.loginuid container.id=%container.id evt.type=%evt.type evt.res=%evt.res proc.pid=%proc.pid proc.cwd=%proc.cwd proc.ppid=%proc.ppid proc.pcmdline=%proc.pcmdline proc.sid=%proc.sid proc.exepath=%proc.exepath user.uid=%user.uid user.loginname=%user.loginname group.gid=%group.gid group.name=%group.name container.name=%container.name image=%container.image.repository exe_flags=%evt.arg.flags)" + spawned_process + and (proc.exe startswith "/dev/shm/" or + (proc.cwd startswith "/dev/shm/" and proc.exe startswith "./" ) or + (shell_procs and proc.args startswith "-c /dev/shm") or + (shell_procs and proc.args startswith "-i /dev/shm") or + (shell_procs and proc.args startswith "/dev/shm") or + (proc.cwd startswith "/dev/shm/" and proc.args startswith "./" )) + and not container.image.repository in (falco_privileged_images, trusted_images) + output: File execution detected from /dev/shm (evt_res=%evt.res file=%fd.name proc_cwd=%proc.cwd proc_pcmdline=%proc.pcmdline user_loginname=%user.loginname group_gid=%group.gid group_name=%group.name 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 %container.info) priority: WARNING - tags: [host, container, mitre_execution, mitre_defense_evasion, T1036.005, T1059.004] - + tags: [maturity_stable, host, container, mitre_execution, T1059.004] + # List of allowed container images that are known to execute binaries not part of their base image. -# Users can use this list to better tune the rule below (i.e reducing false positives) by considering their workloads, -# since this requires application specific knowledge. - list: known_drop_and_execute_containers items: [] - rule: Drop and execute new binary in container - desc: + desc: > Detect if an executable not belonging to the base image of a container is being executed. The drop and execute pattern can be observed very often after an attacker gained an initial foothold. is_exe_upper_layer filter field only applies for container runtimes that use overlayfs as union mount filesystem. + Adopters can utilize the provided template list known_drop_and_execute_containers containing allowed container + images known to execute binaries not included in their base image. Alternatively, you could exclude non-production + namespaces in Kubernetes settings by adjusting the rule further. This helps reduce noise by applying application + and environment-specific knowledge to this rule. Common anti-patterns include administrators or SREs performing + ad-hoc debugging. condition: > spawned_process and container and proc.is_exe_upper_layer=true and not container.image.repository in (known_drop_and_execute_containers) - output: > - Executing binary not part of base image (user=%user.name user_loginuid=%user.loginuid user_uid=%user.uid comm=%proc.cmdline exe=%proc.exe container_id=%container.id - image=%container.image.repository proc.name=%proc.name proc.sname=%proc.sname proc.pname=%proc.pname proc.aname[2]=%proc.aname[2] exe_flags=%evt.arg.flags - proc.exe_ino=%proc.exe_ino proc.exe_ino.ctime=%proc.exe_ino.ctime proc.exe_ino.mtime=%proc.exe_ino.mtime proc.exe_ino.ctime_duration_proc_start=%proc.exe_ino.ctime_duration_proc_start - proc.exepath=%proc.exepath proc.cwd=%proc.cwd proc.tty=%proc.tty container.start_ts=%container.start_ts proc.sid=%proc.sid proc.vpgid=%proc.vpgid evt.res=%evt.res) - priority: CRITICAL - tags: [container, mitre_persistence, TA0003] + output: Executing binary not part of base image (proc_exe=%proc.exe proc_sname=%proc.sname gparent=%proc.aname[2] proc_exe_ino_ctime=%proc.exe_ino.ctime proc_exe_ino_mtime=%proc.exe_ino.mtime proc_exe_ino_ctime_duration_proc_start=%proc.exe_ino.ctime_duration_proc_start proc_cwd=%proc.cwd container_start_ts=%container.start_ts 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 %container.info) + priority: CRITICAL + tags: [maturity_stable, container, process, mitre_persistence, TA0003, PCI_DSS_11.5.1] -# Application rules have moved to application_rules.yaml. Please look -# there if you want to enable them by adding to -# falco_rules.local.yaml. +# RFC1918 addresses were assigned for private network usage +- list: rfc_1918_addresses + items: ['"10.0.0.0/8"', '"172.16.0.0/12"', '"192.168.0.0/16"'] + +- macro: outbound + condition: > + (((evt.type = connect and evt.dir=<) or + (evt.type in (sendto,sendmsg) and evt.dir=< and + fd.l4proto != tcp and fd.connected=false and fd.name_changed=true)) and + (fd.typechar = 4 or fd.typechar = 6) and + (fd.ip != "0.0.0.0" and fd.net != "127.0.0.0/8" and not fd.snet in (rfc_1918_addresses)) and + (evt.rawres >= 0 or evt.res = EINPROGRESS)) + +- list: ssh_non_standard_ports + items: [80, 8080, 88, 443, 8443, 53, 4444] + +- macro: ssh_non_standard_ports_network + condition: (fd.sport in (ssh_non_standard_ports)) + +- rule: Disallowed SSH Connection Non Standard Port + desc: > + Detect any new outbound SSH connection from the host or container using a non-standard port. This rule holds the potential + to detect a family of reverse shells that cause the victim machine to connect back out over SSH, with STDIN piped from + the SSH connection to a shell's STDIN, and STDOUT of the shell piped back over SSH. Such an attack can be launched against + any app that is vulnerable to command injection. The upstream rule only covers a limited selection of non-standard ports. + We suggest adding more ports, potentially incorporating ranges based on your environment's knowledge and custom SSH port + configurations. This rule can complement the "Redirect STDOUT/STDIN to Network Connection in Container" or + "Disallowed SSH Connection" rule. + condition: > + outbound + and proc.exe endswith ssh + and fd.l4proto=tcp + and ssh_non_standard_ports_network + output: Disallowed SSH Connection (connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto 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 %container.info) + priority: NOTICE + tags: [maturity_stable, host, container, network, process, mitre_execution, T1059] + +- list: known_memfd_execution_binaries + items: [] + +- macro: known_memfd_execution_processes + condition: (proc.name in (known_memfd_execution_binaries)) + +- rule: Fileless execution via memfd_create + desc: > + Detect if a binary is executed from memory using the memfd_create technique. This is a well-known defense evasion + technique for executing malware on a victim machine without storing the payload on disk and to avoid leaving traces + about what has been executed. Adopters can whitelist processes that may use fileless execution for benign purposes + by adding items to the list known_memfd_execution_processes. + condition: > + spawned_process + and proc.is_exe_from_memfd=true + and not known_memfd_execution_processes + output: Fileless execution via memfd_create (container_start_ts=%container.start_ts proc_cwd=%proc.cwd evt_res=%evt.res proc_sname=%proc.sname gparent=%proc.aname[2] 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 %container.info) + priority: CRITICAL + tags: [maturity_stable, host, container, process, mitre_defense_evasion, T1620] diff --git a/kubezero/falco/rules.patch b/kubezero/falco/rules.patch index fef1f75..58521a6 100644 --- a/kubezero/falco/rules.patch +++ b/kubezero/falco/rules.patch @@ -1,60 +1,29 @@ ---- falco_rules.yaml 2023-07-05 11:42:09.732973942 +0000 -+++ zdt_falco_rules.yaml 2023-07-05 13:30:14.184038126 +0000 -@@ -270,7 +270,7 @@ +--- falco_rules.yaml 2023-11-07 16:26:40.171716913 +0000 ++++ zdt_falco_rules.yaml 2023-11-07 16:30:24.912804117 +0000 +@@ -171,7 +171,7 @@ # A canonical set of processes that run other programs with different # privileges or as a different user. - list: userexec_binaries - items: [sudo, su, suexec, critical-stack, dzdo] + items: [doas, sudo, su, suexec, critical-stack, dzdo] - - list: known_setuid_binaries - items: [ -@@ -2298,27 +2298,28 @@ - - macro: user_known_non_sudo_setuid_conditions - condition: user.name=root + - list: user_mgmt_binaries + items: [login_binaries, passwd_binaries, shadowutils_binaries] +@@ -200,7 +200,7 @@ + ] -+# Disabled for now due to buysbox noise - # sshd, mail programs attempt to setuid to root even when running as non-root. Excluding here to avoid meaningless FPs --- rule: Non sudo setuid -- desc: > -- an attempt to change users by calling setuid. sudo/su are excluded. users "root" and "nobody" -- suing to itself are also excluded, as setuid calls typically involve dropping privileges. -- condition: > -- evt.type=setuid and evt.dir=> -- and (known_user_in_container or not container) -- and not (user.name=root or user.uid=0) -- and not somebody_becoming_themselves -- and not proc.name in (known_setuid_binaries, userexec_binaries, mail_binaries, docker_binaries, -- nomachine_binaries) -- and not proc.name startswith "runc:" -- and not java_running_sdjagent -- and not nrpe_becoming_nagios -- and not user_known_non_sudo_setuid_conditions -- output: > -- Unexpected setuid call by non-sudo, non-root program (user=%user.name user_loginuid=%user.loginuid cur_uid=%user.uid parent=%proc.pname -- command=%proc.cmdline pid=%proc.pid uid=%evt.arg.uid container_id=%container.id image=%container.image.repository) -- priority: NOTICE -- tags: [host, container, users, mitre_privilege_escalation, T1548.001] -+#- rule: Non sudo setuid -+# desc: > -+# an attempt to change users by calling setuid. sudo/su are excluded. users "root" and "nobody" -+# suing to itself are also excluded, as setuid calls typically involve dropping privileges. -+# condition: > -+# evt.type=setuid and evt.dir=> -+# and (known_user_in_container or not container) -+# and not (user.name=root or user.uid=0) -+# and not somebody_becoming_themselves -+# and not proc.name in (known_setuid_binaries, userexec_binaries, mail_binaries, docker_binaries, -+# nomachine_binaries) -+# and not proc.name startswith "runc:" -+# and not java_running_sdjagent -+# and not nrpe_becoming_nagios -+# and not user_known_non_sudo_setuid_conditions -+# output: > -+# Unexpected setuid call by non-sudo, non-root program (user=%user.name user_loginuid=%user.loginuid cur_uid=%user.uid parent=%proc.pname -+# command=%proc.cmdline pid=%proc.pid uid=%evt.arg.uid container_id=%container.id image=%container.image.repository) -+# priority: NOTICE -+# tags: [host, container, users, mitre_privilege_escalation, T1548.001] + - list: sensitive_file_names +- items: [/etc/shadow, /etc/sudoers, /etc/pam.conf, /etc/security/pwquality.conf] ++ items: [/etc/shadow, /etc/doas.d/doas.conf, /etc/sudoers, /etc/pam.conf, /etc/security/pwquality.conf] - - macro: user_known_user_management_activities - condition: (never_true) + - list: sensitive_directory_names + items: [/, /etc, /etc/, /root, /root/] +@@ -208,7 +208,7 @@ + - macro: sensitive_files + condition: > + ((fd.name startswith /etc and fd.name in (sensitive_file_names)) or +- fd.directory in (/etc/sudoers.d, /etc/pam.d)) ++ fd.directory in (/etc/sudoers.d, /etc/pam.d, /etc/doas.d)) + + # Indicates that the process is new. Currently detected using time + # since process was started, using a threshold of 5 seconds. diff --git a/kubezero/falco/zdt_falco_rules.yaml b/kubezero/falco/zdt_falco_rules.yaml index 66f2cae..350693c 100644 --- a/kubezero/falco/zdt_falco_rules.yaml +++ b/kubezero/falco/zdt_falco_rules.yaml @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 # # Copyright (C) 2023 The Falco Authors. # @@ -15,9 +16,16 @@ # limitations under the License. # +# Information about rules tags and fields can be found here: https://falco.org/docs/rules/#tags-for-current-falco-ruleset +# The initial item in the `tags` fields reflects the maturity level of the rules introduced upon the proposal https://github.com/falcosecurity/rules/blob/main/proposals/20230605-rules-adoption-management-maturity-framework.md +# `tags` fields also include information about the type of workload inspection (host and/or container), and Mitre Attack killchain phases and Mitre TTP code(s) +# Mitre Attack References: +# [1] https://attack.mitre.org/tactics/enterprise/ +# [2] https://raw.githubusercontent.com/mitre/cti/master/enterprise-attack/enterprise-attack.json + # Starting with version 8, the Falco engine supports exceptions. # However the Falco rules file does not use them by default. -- required_engine_version: 17 +- required_engine_version: 0.26.0 # Currently disabled as read/write are ignored syscalls. The nearly # similar open_write/open_read check for files being opened for @@ -27,21 +35,12 @@ # - macro: read # condition: (syscall.type=read and evt.dir=> and fd.type in (file, directory)) -# Information about rules tags and fields can be found here: https://falco.org/docs/rules/#tags-for-current-falco-ruleset -# `tags` fields also include information about the type of workload inspection, Mitre Attack killchain phases and Mitre TTP code(s) -# Mitre Attack References: -# [1] https://attack.mitre.org/tactics/enterprise/ -# [2] https://raw.githubusercontent.com/mitre/cti/master/enterprise-attack/enterprise-attack.json - - macro: open_write condition: (evt.type in (open,openat,openat2) and evt.is_open_write=true and fd.typechar='f' and fd.num>=0) - macro: open_read condition: (evt.type in (open,openat,openat2) and evt.is_open_read=true and fd.typechar='f' and fd.num>=0) -- macro: open_directory - condition: (evt.type in (open,openat,openat2) and evt.is_open_read=true and fd.typechar='d' and fd.num>=0) - # Failed file open attempts, useful to detect threat actors making mistakes # https://man7.org/linux/man-pages/man3/errno.3.html # evt.res=ENOENT - No such file or directory @@ -49,11 +48,27 @@ - macro: open_file_failed condition: (evt.type in (open,openat,openat2) and fd.typechar='f' and fd.num=-1 and evt.res startswith E) +# This macro `never_true` is used as placeholder for tuning negative logical sub-expressions, for example +# - macro: allowed_ssh_hosts +# condition: (never_true) +# can be used in a rules' expression with double negation `and not allowed_ssh_hosts` which effectively evaluates +# to true and does nothing, the perfect empty template for `logical` cases as opposed to list templates. +# When tuning the rule you can override the macro with something useful, e.g. +# - macro: allowed_ssh_hosts +# condition: (evt.hostname contains xyz) - macro: never_true condition: (evt.num=0) -- macro: always_true - condition: (evt.num>=0) +# This macro `always_true` is the flip side of the macro `never_true` and currently is commented out as +# it is not used. You can use it as placeholder for a positive logical sub-expression tuning template +# macro, e.g. `and custom_procs`, where +# - macro: custom_procs +# condition: (always_true) +# later you can customize, override the macros to something like +# - macro: custom_procs +# condition: (proc.name in (custom1, custom2, custom3)) +# - macro: always_true +# condition: (evt.num>=0) # In some cases, such as dropped system call events, information about # the process name may be missing. For some rules that really depend @@ -62,23 +77,6 @@ - macro: proc_name_exists condition: (proc.name!="") -- macro: rename - condition: (evt.type in (rename, renameat, renameat2)) - -- macro: mkdir - condition: (evt.type in (mkdir, mkdirat)) - -- macro: remove - condition: (evt.type in (rmdir, unlink, unlinkat)) - -- macro: modify - condition: (rename or remove) - -# %evt.arg.flags available for evt.dir=>, but only for umount2 -# %evt.arg.name is path and available for evt.dir=< -# - macro: umount -# condition: (evt.type in (umount, umount2)) - - macro: spawned_process condition: (evt.type in (execve, execveat) and evt.dir=<) @@ -88,78 +86,21 @@ - macro: create_hardlink condition: (evt.type in (link, linkat) and evt.dir=<) -- macro: chmod - condition: (evt.type in (chmod, fchmod, fchmodat) and evt.dir=<) - - macro: kernel_module_load condition: (evt.type in (init_module, finit_module) and evt.dir=<) +- macro: dup + condition: (evt.type in (dup, dup2, dup3)) + # File categories -- macro: bin_dir - condition: (fd.directory in (/bin, /sbin, /usr/bin, /usr/sbin)) - -- macro: bin_dir_mkdir - condition: > - (evt.arg.path startswith /bin/ or - evt.arg.path startswith /sbin/ or - evt.arg.path startswith /usr/bin/ or - evt.arg.path startswith /usr/sbin/) - -- macro: bin_dir_rename - condition: > - (evt.arg.path startswith /bin/ or - evt.arg.path startswith /sbin/ or - evt.arg.path startswith /usr/bin/ or - evt.arg.path startswith /usr/sbin/ or - evt.arg.name startswith /bin/ or - evt.arg.name startswith /sbin/ or - evt.arg.name startswith /usr/bin/ or - evt.arg.name startswith /usr/sbin/ or - evt.arg.oldpath startswith /bin/ or - evt.arg.oldpath startswith /sbin/ or - evt.arg.oldpath startswith /usr/bin/ or - evt.arg.oldpath startswith /usr/sbin/ or - evt.arg.newpath startswith /bin/ or - evt.arg.newpath startswith /sbin/ or - evt.arg.newpath startswith /usr/bin/ or - evt.arg.newpath startswith /usr/sbin/) - - macro: etc_dir condition: (fd.name startswith /etc/) -# This detects writes immediately below / or any write anywhere below /root -- macro: root_dir - condition: (fd.directory=/ or fd.name startswith /root/) - - list: shell_binaries items: [ash, bash, csh, ksh, sh, tcsh, zsh, dash] -- list: ssh_binaries - items: [ - sshd, sftp-server, ssh-agent, - ssh, scp, sftp, - ssh-keygen, ssh-keysign, ssh-keyscan, ssh-add - ] - -- list: shell_mgmt_binaries - items: [add-shell, remove-shell] - - macro: shell_procs - condition: proc.name in (shell_binaries) - -- list: coreutils_binaries - items: [ - truncate, sha1sum, numfmt, fmt, fold, uniq, cut, who, - groups, csplit, sort, expand, printf, printenv, unlink, tee, chcon, stat, - basename, split, nice, "yes", whoami, sha224sum, hostid, users, stdbuf, - base64, unexpand, cksum, od, paste, nproc, pathchk, sha256sum, wc, test, - comm, arch, du, factor, sha512sum, md5sum, tr, runcon, env, dirname, - tsort, join, shuf, install, logname, pinky, nohup, expr, pr, tty, timeout, - tail, "[", seq, sha384sum, nl, head, id, mkfifo, sum, dircolors, ptx, shred, - tac, link, chroot, vdir, chown, touch, ls, dd, uname, "true", pwd, date, - chgrp, chmod, mktemp, cat, mknod, sync, ln, "false", rm, mv, cp, echo, - readlink, sleep, stty, mkdir, df, dir, rmdir, touch - ] + condition: (proc.name in (shell_binaries)) # dpkg -L login | grep bin | xargs ls -ld | grep -v '^d' | awk '{print $9}' | xargs -L 1 basename | tr "\\n" "," - list: login_binaries @@ -186,15 +127,6 @@ newusers, pwck, pwconv, pwunconv, useradd, userdel, usermod, vigr, vipw, unix_chkpwd ] -- list: sysdigcloud_binaries - items: [setup-backend, dragent, sdchecks] - -- list: k8s_binaries - items: [hyperkube, skydns, kube2sky, exechealthz, weave-net, loopback, bridge, openshift-sdn, openshift] - -- list: lxd_binaries - items: [lxd, lxcfs] - - list: http_server_binaries items: [nginx, httpd, httpd-foregroun, lighttpd, apache, apache2] @@ -210,15 +142,8 @@ - list: gitlab_binaries items: [gitlab-shell, gitlab-mon, gitlab-runner-b, git] -- list: interpreted_binaries - items: [lua, node, perl, perl5, perl6, php, python, python2, python3, ruby, tcl] - -- macro: interpreted_procs - condition: > - (proc.name in (interpreted_binaries)) - - macro: server_procs - condition: proc.name in (http_server_binaries, db_server_binaries, docker_binaries, sshd) + condition: (proc.name in (http_server_binaries, db_server_binaries, docker_binaries, sshd)) # The explicit quotes are needed to avoid the - characters being # interpreted by the filter expression. @@ -227,12 +152,6 @@ repoquery, rpmkeys, rpmq, yum-cron, yum-config-mana, yum-debug-dump, abrt-action-sav, rpmdb_stat, microdnf, rhn_check, yumdb] -- list: openscap_rpm_binaries - items: [probe_rpminfo, probe_rpmverify, probe_rpmverifyfile, probe_rpmverifypackage] - -- macro: rpm_procs - condition: (proc.name in (rpm_binaries, openscap_rpm_binaries) or proc.name in (salt-call, salt-minion)) - - list: deb_binaries items: [dpkg, dpkg-preconfigu, dpkg-reconfigur, dpkg-divert, apt, apt-get, aptitude, frontend, preinst, add-apt-reposit, apt-auto-remova, apt-key, @@ -246,45 +165,17 @@ - list: package_mgmt_binaries items: [rpm_binaries, deb_binaries, update-alternat, gem, npm, python_package_managers, sane-utils.post, alternatives, chef-client, apk, snapd] -- macro: package_mgmt_procs - condition: proc.name in (package_mgmt_binaries) - -- macro: package_mgmt_ancestor_procs - condition: proc.pname in (package_mgmt_binaries) or - proc.aname[2] in (package_mgmt_binaries) or - proc.aname[3] in (package_mgmt_binaries) or - proc.aname[4] in (package_mgmt_binaries) - -- macro: coreos_write_ssh_dir - condition: (proc.name=update-ssh-keys and fd.name startswith /home/core/.ssh) - - macro: run_by_package_mgmt_binaries - condition: proc.aname in (package_mgmt_binaries, needrestart) - -- list: ssl_mgmt_binaries - items: [ca-certificates] - -- list: dhcp_binaries - items: [dhclient, dhclient-script, 11-dhclient] + condition: (proc.aname in (package_mgmt_binaries, needrestart)) # A canonical set of processes that run other programs with different # privileges or as a different user. - list: userexec_binaries items: [doas, sudo, su, suexec, critical-stack, dzdo] -- list: known_setuid_binaries - items: [ - sshd, dbus-daemon-lau, ping, ping6, critical-stack-, pmmcli, - filemng, PassengerAgent, bwrap, osdetect, nginxmng, sw-engine-fpm, - start-stop-daem - ] - - list: user_mgmt_binaries items: [login_binaries, passwd_binaries, shadowutils_binaries] -- list: dev_creation_binaries - items: [blkid, rename_device, update_engine, sgdisk] - - list: hids_binaries items: [aide, aide.wrapper, update-aide.con, logcheck, syslog-summary, osqueryd, ossec-syscheckd] @@ -294,9 +185,6 @@ - list: nomachine_binaries items: [nxexec, nxnode.bin, nxserver.bin, nxclient.bin] -- macro: system_procs - condition: proc.name in (coreutils_binaries, user_mgmt_binaries) - - list: mail_binaries items: [ sendmail, sendmail-msp, postfix, procmail, exim4, @@ -312,209 +200,22 @@ ] - list: sensitive_file_names - items: [/etc/shadow, /etc/sudoers, /etc/pam.conf, /etc/security/pwquality.conf] + items: [/etc/shadow, /etc/doas.d/doas.conf, /etc/sudoers, /etc/pam.conf, /etc/security/pwquality.conf] - list: sensitive_directory_names items: [/, /etc, /etc/, /root, /root/] - macro: sensitive_files condition: > - fd.name startswith /etc and - (fd.name in (sensitive_file_names) - or fd.directory in (/etc/sudoers.d, /etc/pam.d)) + ((fd.name startswith /etc and fd.name in (sensitive_file_names)) or + fd.directory in (/etc/sudoers.d, /etc/pam.d, /etc/doas.d)) # Indicates that the process is new. Currently detected using time # since process was started, using a threshold of 5 seconds. - macro: proc_is_new - condition: proc.duration <= 5000000000 - -# Network -- macro: inbound - condition: > - (((evt.type in (accept,accept4,listen) and evt.dir=<) or - (evt.type in (recvfrom,recvmsg) and evt.dir=< and - fd.l4proto != tcp and fd.connected=false and fd.name_changed=true)) and - (fd.typechar = 4 or fd.typechar = 6) and - (fd.ip != "0.0.0.0" and fd.net != "127.0.0.0/8") and - (evt.rawres >= 0 or evt.res = EINPROGRESS)) - -# RFC1918 addresses were assigned for private network usage -- list: rfc_1918_addresses - items: ['"10.0.0.0/8"', '"172.16.0.0/12"', '"192.168.0.0/16"'] - -- macro: outbound - condition: > - (((evt.type = connect and evt.dir=<) or - (evt.type in (sendto,sendmsg) and evt.dir=< and - fd.l4proto != tcp and fd.connected=false and fd.name_changed=true)) and - (fd.typechar = 4 or fd.typechar = 6) and - (fd.ip != "0.0.0.0" and fd.net != "127.0.0.0/8" and not fd.snet in (rfc_1918_addresses)) and - (evt.rawres >= 0 or evt.res = EINPROGRESS)) - -# Very similar to inbound/outbound, but combines the tests together -# for efficiency. -- macro: inbound_outbound - condition: > - ((((evt.type in (accept,accept4,listen,connect) and evt.dir=<)) and - (fd.typechar = 4 or fd.typechar = 6)) and - (fd.ip != "0.0.0.0" and fd.net != "127.0.0.0/8") and - (evt.rawres >= 0 or evt.res = EINPROGRESS)) - -- macro: ssh_port - condition: fd.sport=22 - -# In a local/user rules file, you could override this macro to -# enumerate the servers for which ssh connections are allowed. For -# example, you might have a ssh gateway host for which ssh connections -# are allowed. -# -# In the main falco rules file, there isn't any way to know the -# specific hosts for which ssh access is allowed, so this macro just -# repeats ssh_port, which effectively allows ssh from all hosts. In -# the overridden macro, the condition would look something like -# "fd.sip="a.b.c.d" or fd.sip="e.f.g.h" or ..." -- macro: allowed_ssh_hosts - condition: ssh_port - -- rule: Disallowed SSH Connection - desc: Detect any new ssh connection to a host other than those in an allowed group of hosts - condition: (inbound_outbound) and ssh_port and not allowed_ssh_hosts - enabled: false - output: Disallowed SSH Connection (command=%proc.cmdline pid=%proc.pid connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository) - priority: NOTICE - tags: [host, container, network, mitre_command_and_control, mitre_lateral_movement, T1021.004] - -# These rules and supporting macros are more of an example for how to -# use the fd.*ip and fd.*ip.name fields to match connection -# information against ips, netmasks, and complete domain names. -# -# To use this rule, you should enable it and -# populate allowed_{source,destination}_{ipaddrs,networks,domains} with the -# values that make sense for your environment. - -# Note that this can be either individual IPs or netmasks -- list: allowed_outbound_destination_ipaddrs - items: ['"127.0.0.1"', '"8.8.8.8"'] - -- list: allowed_outbound_destination_networks - items: ['"127.0.0.1/8"'] - -- list: allowed_outbound_destination_domains - items: [google.com, www.yahoo.com] - -- rule: Unexpected outbound connection destination - desc: Detect any outbound connection to a destination outside of an allowed set of ips, networks, or domain names - condition: > - outbound and not - ((fd.sip in (allowed_outbound_destination_ipaddrs)) or - (fd.snet in (allowed_outbound_destination_networks)) or - (fd.sip.name in (allowed_outbound_destination_domains))) - enabled: false - output: Disallowed outbound connection destination (command=%proc.cmdline pid=%proc.pid connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository) - priority: NOTICE - tags: [host, container, network, mitre_command_and_control, TA0011] - -- list: allowed_inbound_source_ipaddrs - items: ['"127.0.0.1"'] - -- list: allowed_inbound_source_networks - items: ['"127.0.0.1/8"', '"10.0.0.0/8"'] - -- list: allowed_inbound_source_domains - items: [google.com] - -- rule: Unexpected inbound connection source - desc: Detect any inbound connection from a source outside of an allowed set of ips, networks, or domain names - condition: > - inbound and not - ((fd.cip in (allowed_inbound_source_ipaddrs)) or - (fd.cnet in (allowed_inbound_source_networks)) or - (fd.cip.name in (allowed_inbound_source_domains))) - enabled: false - output: Disallowed inbound connection source (command=%proc.cmdline pid=%proc.pid connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository) - priority: NOTICE - tags: [host, container, network, mitre_command_and_control, TA0011] - -- list: bash_config_filenames - items: [.bashrc, .bash_profile, .bash_history, .bash_login, .bash_logout, .inputrc, .profile] - -- list: bash_config_files - items: [/etc/profile, /etc/bashrc] - -# Covers both csh and tcsh -- list: csh_config_filenames - items: [.cshrc, .login, .logout, .history, .tcshrc, .cshdirs] - -- list: csh_config_files - items: [/etc/csh.cshrc, /etc/csh.login] - -- list: zsh_config_filenames - items: [.zshenv, .zprofile, .zshrc, .zlogin, .zlogout] - -- list: shell_config_filenames - items: [bash_config_filenames, csh_config_filenames, zsh_config_filenames] - -- list: shell_config_files - items: [bash_config_files, csh_config_files] - -- list: shell_config_directories - items: [/etc/zsh] - -- macro: user_known_shell_config_modifiers - condition: (never_true) - -- rule: Modify Shell Configuration File - desc: Detect attempt to modify shell configuration files - condition: > - open_write and - (fd.filename in (shell_config_filenames) or - fd.name in (shell_config_files) or - fd.directory in (shell_config_directories)) - and not proc.name in (shell_binaries) - and not exe_running_docker_save - and not user_known_shell_config_modifiers - output: > - a shell configuration file has been modified (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid pcmdline=%proc.pcmdline file=%fd.name container_id=%container.id image=%container.image.repository) - priority: - WARNING - tags: [host, container, filesystem, mitre_persistence, T1546.004] - -# This rule is not enabled by default, as there are many legitimate -# readers of shell config files. -- rule: Read Shell Configuration File - desc: Detect attempts to read shell configuration files by non-shell programs - condition: > - open_read and - (fd.filename in (shell_config_filenames) or - fd.name in (shell_config_files) or - fd.directory in (shell_config_directories)) and - (not proc.name in (shell_binaries)) - enabled: false - output: > - a shell configuration file was read by a non-shell program (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid file=%fd.name container_id=%container.id image=%container.image.repository) - priority: - WARNING - tags: [host, container, filesystem, mitre_discovery, T1546.004] - -- macro: user_known_cron_jobs - condition: (never_true) - -- rule: Schedule Cron Jobs - desc: Detect cron jobs scheduled - condition: > - ((open_write and fd.name startswith /etc/cron) or - (spawned_process and proc.name = "crontab")) and - not user_known_cron_jobs - enabled: false - output: > - Cron jobs were scheduled to run (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid - file=%fd.name container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag) - priority: - NOTICE - tags: [host, container, filesystem, mitre_persistence, T1053.003] + condition: (proc.duration <= 5000000000) # Use this to test whether the event occurred within a container. - # When displaying container information in the output field, use # %container.info, without any leading term (file=%fd.name # %container.info user=%user.name user_loginuid=%user.loginuid, and not file=%fd.name @@ -524,12 +225,6 @@ - macro: container condition: (container.id != host) -- macro: container_started - condition: > - ((evt.type = container or - (spawned_process and proc.vpid=1)) and - container.image.repository != incomplete) - - macro: interactive condition: > ((proc.aname=sshd and proc.name != sshd) or @@ -546,35 +241,14 @@ - list: sshkit_script_binaries items: [10_etc_sudoers., 10_passwd_group] -- list: plesk_binaries - items: [sw-engine, sw-engine-fpm, sw-engine-kv, filemng, f2bmng] - # System users that should never log into a system. Consider adding your own # service users (e.g. 'apache' or 'mysqld') here. - macro: system_users - condition: user.name in (bin, daemon, games, lp, mail, nobody, sshd, sync, uucp, www-data) - -- macro: httpd_writing_ssl_conf - condition: > - (proc.pname=run-httpd and - (proc.cmdline startswith "sed -ri" or proc.cmdline startswith "sed -i") and - (fd.name startswith /etc/httpd/conf.d/ or fd.name startswith /etc/httpd/conf)) - -- macro: userhelper_writing_etc_security - condition: (proc.name=userhelper and fd.name startswith /etc/security) + condition: (user.name in (bin, daemon, games, lp, mail, nobody, sshd, sync, uucp, www-data)) - macro: ansible_running_python condition: (proc.name in (python, pypy, python3) and proc.cmdline contains ansible) -- macro: python_running_chef - condition: (proc.name=python and (proc.cmdline contains yum-dump.py or proc.cmdline="python /usr/bin/chef-monitor.py")) - -- macro: python_running_denyhosts - condition: > - (proc.name=python and - (proc.cmdline contains /usr/sbin/denyhosts or - proc.cmdline contains /usr/local/bin/denyhosts.py)) - # Qualys seems to run a variety of shell subprocesses, at various # levels. This checks at a few levels without the cost of a full # proc.aname, which traverses the full parent hierarchy. @@ -585,21 +259,6 @@ proc.aname[3]=qualys-cloud-ag or proc.aname[4]=qualys-cloud-ag) -- macro: run_by_sumologic_securefiles - condition: > - ((proc.cmdline="usermod -a -G sumologic_collector" or - proc.cmdline="groupadd sumologic_collector") and - (proc.pname=secureFiles.sh and proc.aname[2]=java)) - -- macro: run_by_yum - condition: ((proc.pname=sh and proc.aname[2]=yum) or - (proc.aname[2]=sh and proc.aname[3]=yum)) - -- macro: run_by_ms_oms - condition: > - (proc.aname[3] startswith omsagent- or - proc.aname[3] startswith scx-) - - macro: run_by_google_accounts_daemon condition: > (proc.aname[1] startswith google_accounts or @@ -612,12 +271,6 @@ proc.aname[2]=chef-client or proc.aname[3]=chef-client or proc.name=chef-client) -- macro: run_by_adclient - condition: (proc.aname[2]=adclient or proc.aname[3]=adclient or proc.aname[4]=adclient) - -- macro: run_by_centrify - condition: (proc.aname[2]=centrify or proc.aname[3]=centrify or proc.aname[4]=centrify) - # Also handles running semi-indirectly via scl - macro: run_by_foreman condition: > @@ -625,40 +278,12 @@ ((proc.pname in (rake, ruby, scl) and proc.aname[5] in (tfm-rake,tfm-ruby)) or (proc.pname=scl and proc.aname[2] in (tfm-rake,tfm-ruby)))) -- macro: java_running_sdjagent - condition: proc.name=java and proc.cmdline contains sdjagent.jar - -- macro: kubelet_running_loopback - condition: (proc.pname=kubelet and proc.name=loopback) - - macro: python_mesos_marathon_scripting condition: (proc.pcmdline startswith "python3 /marathon-lb/marathon_lb.py") - macro: splunk_running_forwarder condition: (proc.pname=splunkd and proc.cmdline startswith "sh -c /opt/splunkforwarder") -- macro: parent_supervise_running_multilog - condition: (proc.name=multilog and proc.pname=supervise) - -- macro: supervise_writing_status - condition: (proc.name in (supervise,svc) and fd.name startswith "/etc/sb/") - -- macro: pki_realm_writing_realms - condition: (proc.cmdline startswith "bash /usr/local/lib/pki/pki-realm" and fd.name startswith /etc/pki/realms) - -- macro: htpasswd_writing_passwd - condition: (proc.name=htpasswd and fd.name=/etc/nginx/.htpasswd) - -- macro: lvprogs_writing_conf - condition: > - (proc.name in (dmeventd,lvcreate,pvscan,lvs) and - (fd.name startswith /etc/lvm/archive or - fd.name startswith /etc/lvm/backup or - fd.name startswith /etc/lvm/cache)) - -- macro: ovsdb_writing_openvswitch - condition: (proc.name=ovsdb-server and fd.directory=/etc/openvswitch) - - macro: perl_running_plesk condition: (proc.cmdline startswith "perl /opt/psa/admin/bin/plesk_agent_manager" or proc.pcmdline startswith "perl /opt/psa/admin/bin/plesk_agent_manager") @@ -679,731 +304,60 @@ (fd.name=/etc/shadow or fd.directory=/etc/pam.d)) -- macro: parent_ucf_writing_conf - condition: (proc.pname=ucf and proc.aname[2]=frontend) - -- macro: consul_template_writing_conf - condition: > - ((proc.name=consul-template and fd.name startswith /etc/haproxy) or - (proc.name=reload.sh and proc.aname[2]=consul-template and fd.name startswith /etc/ssl)) - -- macro: countly_writing_nginx_conf - condition: (proc.cmdline startswith "nodejs /opt/countly/bin" and fd.name startswith /etc/nginx) - -- list: ms_oms_binaries - items: [omi.postinst, omsconfig.posti, scx.postinst, omsadmin.sh, omiagent] - -- macro: ms_oms_writing_conf - condition: > - ((proc.name in (omiagent,omsagent,in_heartbeat_r*,omsadmin.sh,PerformInventor,dsc_host) - or proc.pname in (ms_oms_binaries) - or proc.aname[2] in (ms_oms_binaries)) - and (fd.name startswith /etc/opt/omi or fd.name startswith /etc/opt/microsoft/omsagent)) - -- macro: ms_scx_writing_conf - condition: (proc.name in (GetLinuxOS.sh) and fd.name startswith /etc/opt/microsoft/scx) - -- macro: azure_scripts_writing_conf - condition: (proc.pname startswith "bash /var/lib/waagent/" and fd.name startswith /etc/azure) - -- macro: azure_networkwatcher_writing_conf - condition: (proc.name in (NetworkWatcherA) and fd.name=/etc/init.d/AzureNetworkWatcherAgent) - -- macro: couchdb_writing_conf - condition: (proc.name=beam.smp and proc.cmdline contains couchdb and fd.name startswith /etc/couchdb) - -- macro: update_texmf_writing_conf - condition: (proc.name=update-texmf and fd.name startswith /etc/texmf) - -- macro: slapadd_writing_conf - condition: (proc.name=slapadd and fd.name startswith /etc/ldap) - -- macro: openldap_writing_conf - condition: (proc.pname=run-openldap.sh and fd.name startswith /etc/openldap) - -- macro: ucpagent_writing_conf - condition: (proc.name=apiserver and container.image.repository=docker/ucp-agent and fd.name=/etc/authorization_config.cfg) - -- macro: iscsi_writing_conf - condition: (proc.name=iscsiadm and fd.name startswith /etc/iscsi) - -- macro: istio_writing_conf - condition: (proc.name=pilot-agent and fd.name startswith /etc/istio) - -- macro: symantec_writing_conf - condition: > - ((proc.name=symcfgd and fd.name startswith /etc/symantec) or - (proc.name=navdefutil and fd.name=/etc/symc-defutils.conf)) - -- macro: liveupdate_writing_conf - condition: (proc.cmdline startswith "java LiveUpdate" and fd.name in (/etc/liveupdate.conf, /etc/Product.Catalog.JavaLiveUpdate)) - -- macro: rancher_agent - condition: (proc.name=agent and container.image.repository contains "rancher/agent") - -- macro: rancher_network_manager - condition: (proc.name=rancher-bridge and container.image.repository contains "rancher/network-manager") - -- macro: sosreport_writing_files - condition: > - (proc.name=urlgrabber-ext- and proc.aname[3]=sosreport and - (fd.name startswith /etc/pkt/nssdb or fd.name startswith /etc/pki/nssdb)) - -- macro: pkgmgmt_progs_writing_pki - condition: > - (proc.name=urlgrabber-ext- and proc.pname in (yum, yum-cron, repoquery) and - (fd.name startswith /etc/pkt/nssdb or fd.name startswith /etc/pki/nssdb)) - -- macro: update_ca_trust_writing_pki - condition: (proc.pname=update-ca-trust and proc.name=trust and fd.name startswith /etc/pki) - -- macro: brandbot_writing_os_release - condition: proc.name=brandbot and fd.name=/etc/os-release - -- macro: selinux_writing_conf - condition: (proc.name in (semodule,genhomedircon,sefcontext_comp) and fd.name startswith /etc/selinux) - -- list: veritas_binaries - items: [vxconfigd, sfcache, vxclustadm, vxdctl, vxprint, vxdmpadm, vxdisk, vxdg, vxassist, vxtune] - - macro: veritas_driver_script condition: (proc.cmdline startswith "perl /opt/VRTSsfmh/bin/mh_driver.pl") -- macro: veritas_progs - condition: (proc.name in (veritas_binaries) or veritas_driver_script) - -- macro: veritas_writing_config - condition: (veritas_progs and (fd.name startswith /etc/vx or fd.name startswith /etc/opt/VRTS or fd.name startswith /etc/vom)) - -- macro: nginx_writing_conf - condition: (proc.name in (nginx,nginx-ingress-c,nginx-ingress) and (fd.name startswith /etc/nginx or fd.name startswith /etc/ingress-controller)) - -- macro: nginx_writing_certs - condition: > - (((proc.name=openssl and proc.pname=nginx-launch.sh) or proc.name=nginx-launch.sh) and fd.name startswith /etc/nginx/certs) - -- macro: chef_client_writing_conf - condition: (proc.pcmdline startswith "chef-client /opt/gitlab" and fd.name startswith /etc/gitlab) - -- macro: centrify_writing_krb - condition: (proc.name in (adjoin,addns) and fd.name startswith /etc/krb5) - -- macro: sssd_writing_krb - condition: (proc.name=adcli and proc.aname[2]=sssd and fd.name startswith /etc/krb5) - -- macro: cockpit_writing_conf - condition: > - ((proc.pname=cockpit-kube-la or proc.aname[2]=cockpit-kube-la) - and fd.name startswith /etc/cockpit) - -- macro: ipsec_writing_conf - condition: (proc.name=start-ipsec.sh and fd.directory=/etc/ipsec) - -- macro: exe_running_docker_save - condition: > - proc.name = "exe" - and (proc.cmdline contains "/var/lib/docker" - or proc.cmdline contains "/var/run/docker") - and proc.pname in (dockerd, docker, dockerd-current, docker-current) - -# Ideally we'd have a length check here as well but -# filterchecks don't have operators like len() -- macro: sed_temporary_file - condition: (proc.name=sed and fd.name startswith "/etc/sed") - -- macro: python_running_get_pip - condition: (proc.cmdline startswith "python get-pip.py") - -- macro: python_running_ms_oms - condition: (proc.cmdline startswith "python /var/lib/waagent/") - -- macro: gugent_writing_guestagent_log - condition: (proc.name=gugent and fd.name=GuestAgent.log) - -- macro: dse_writing_tmp - condition: (proc.name=dse-entrypoint and fd.name=/root/tmp__) - -- macro: zap_writing_state - condition: (proc.name=java and proc.cmdline contains "jar /zap" and fd.name startswith /root/.ZAP) - -- macro: airflow_writing_state - condition: (proc.name=airflow and fd.name startswith /root/airflow) - -- macro: rpm_writing_root_rpmdb - condition: (proc.name=rpm and fd.directory=/root/.rpmdb) - -- macro: maven_writing_groovy - condition: (proc.name=java and proc.cmdline contains "classpath /usr/local/apache-maven" and fd.name startswith /root/.groovy) - -- macro: chef_writing_conf - condition: (proc.name=chef-client and fd.name startswith /root/.chef) - -- macro: kubectl_writing_state - condition: (proc.name in (kubectl,oc) and fd.name startswith /root/.kube) - -- macro: java_running_cassandra - condition: (proc.name=java and proc.cmdline contains "cassandra.jar") - -- macro: cassandra_writing_state - condition: (java_running_cassandra and fd.directory=/root/.cassandra) - -# Istio -- macro: galley_writing_state - condition: (proc.name=galley and fd.name in (known_istio_files)) - -- list: known_istio_files - items: [/healthready, /healthliveness] - -- macro: calico_writing_state - condition: (proc.name=kube-controller and fd.name startswith /status.json and k8s.pod.name startswith calico) - -- macro: calico_writing_envvars - condition: (proc.name=start_runit and fd.name startswith "/etc/envvars" and container.image.repository endswith "calico/node") - -- list: repository_files - items: [sources.list] - -- list: repository_directories - items: [/etc/apt/sources.list.d, /etc/yum.repos.d, /etc/apt] - -- macro: access_repositories - condition: (fd.directory in (repository_directories) or - (fd.name pmatch (repository_directories) and - fd.filename in (repository_files))) - -- macro: modify_repositories - condition: (evt.arg.newpath pmatch (repository_directories)) - -- macro: user_known_update_package_registry - condition: (never_true) - -- rule: Update Package Repository - desc: Detect package repositories get updated - condition: > - ((open_write and access_repositories) or (modify and modify_repositories)) - and not package_mgmt_procs - and not package_mgmt_ancestor_procs - and not exe_running_docker_save - and not user_known_update_package_registry - output: > - Repository files get updated (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid pcmdline=%proc.pcmdline file=%fd.name newpath=%evt.arg.newpath container_id=%container.id image=%container.image.repository) - priority: - NOTICE - tags: [host, container, filesystem, mitre_persistence, T1072] - -# Users should overwrite this macro to specify conditions under which a -# write under the binary dir is ignored. For example, it may be okay to -# install a binary in the context of a ci/cd build. -- macro: user_known_write_below_binary_dir_activities - condition: (never_true) - -- rule: Write below binary dir - desc: an attempt to write to any file below a set of binary directories - condition: > - bin_dir and evt.dir = < and open_write - and not package_mgmt_procs - and not exe_running_docker_save - and not python_running_get_pip - and not python_running_ms_oms - and not user_known_write_below_binary_dir_activities - output: > - File below a known binary directory opened for writing (user=%user.name user_loginuid=%user.loginuid - command=%proc.cmdline pid=%proc.pid file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository) - priority: ERROR - tags: [host, container, filesystem, mitre_persistence, T1543] - -# If you'd like to generally monitor a wider set of directories on top -# of the ones covered by the rule Write below binary dir, you can use -# the following rule and lists. -- list: monitored_directories - items: [/boot, /lib, /lib64, /usr/lib, /usr/local/lib, /usr/local/sbin, /usr/local/bin, /root/.ssh] - - macro: user_ssh_directory condition: (fd.name contains '/.ssh/' and fd.name glob '/home/*/.ssh/*') - macro: directory_traversal condition: (fd.nameraw contains '../' and fd.nameraw glob '*../*../*') -# google_accounts_(daemon) -- macro: google_accounts_daemon_writing_ssh - condition: (proc.name=google_accounts and user_ssh_directory) - -- macro: cloud_init_writing_ssh - condition: (proc.name=cloud-init and user_ssh_directory) - -- macro: mkinitramfs_writing_boot - condition: (proc.pname in (mkinitramfs, update-initramf) and fd.directory=/boot) - -- macro: monitored_dir - condition: > - (fd.directory in (monitored_directories) - or user_ssh_directory) - and not mkinitramfs_writing_boot - -# Add conditions to this macro (probably in a separate file, -# overwriting this macro) to allow for specific combinations of -# programs writing below monitored directories. -# -# Its default value is an expression that always is false, which -# becomes true when the "not ..." in the rule is applied. -- macro: user_known_write_monitored_dir_conditions - condition: (never_true) - -- rule: Write below monitored dir - desc: an attempt to write to any file below a set of monitored directories - condition: > - evt.dir = < and open_write and monitored_dir - and not package_mgmt_procs - and not coreos_write_ssh_dir - and not exe_running_docker_save - and not python_running_get_pip - and not python_running_ms_oms - and not google_accounts_daemon_writing_ssh - and not cloud_init_writing_ssh - and not user_known_write_monitored_dir_conditions - output: > - File below a monitored directory opened for writing (user=%user.name user_loginuid=%user.loginuid - command=%proc.cmdline pid=%proc.pid file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository) - priority: ERROR - tags: [host, container, filesystem, mitre_persistence, T1543] - # ****************************************************************************** # * "Directory traversal monitored file read" requires FALCO_ENGINE_VERSION 13 * # ****************************************************************************** - - rule: Directory traversal monitored file read desc: > - Web applications can be vulnerable to directory traversal attacks that allow accessing files outside of the web app's root directory (e.g. Arbitrary File Read bugs). - System directories like /etc are typically accessed via absolute paths. Access patterns outside of this (here path traversal) can be regarded as suspicious. - This rule includes failed file open attempts. - condition: (open_read or open_file_failed) and (etc_dir or user_ssh_directory or fd.name startswith /root/.ssh or fd.name contains "id_rsa") and directory_traversal and not proc.pname in (shell_binaries) + Web applications can be vulnerable to directory traversal attacks that allow accessing files outside of the web app's root directory + (e.g. Arbitrary File Read bugs). System directories like /etc are typically accessed via absolute paths. Access patterns outside of this + (here path traversal) can be regarded as suspicious. This rule includes failed file open attempts. + condition: > + (open_read or open_file_failed) + and (etc_dir or user_ssh_directory or + fd.name startswith /root/.ssh or + fd.name contains "id_rsa") + and directory_traversal + and not proc.pname in (shell_binaries) enabled: true - output: > - Read monitored file via directory traversal (username=%user.name useruid=%user.uid user_loginuid=%user.loginuid program=%proc.name exe=%proc.exepath - command=%proc.cmdline pid=%proc.pid parent=%proc.pname file=%fd.name fileraw=%fd.nameraw parent=%proc.pname - gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository returncode=%evt.res cwd=%proc.cwd) + output: Read monitored file via directory traversal (file=%fd.name fileraw=%fd.nameraw gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] 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 %container.info) priority: WARNING - tags: [host, container, filesystem, mitre_discovery, mitre_exfiltration, mitre_credential_access, T1555, T1212, T1020, T1552, T1083] - -# The rule below is disabled by default as many system management tools -# like ansible, etc can read these files/paths. Enable it using this macro. -- macro: user_known_read_ssh_information_activities - condition: (never_true) - -- rule: Read ssh information - desc: Any attempt to read files below ssh directories by non-ssh programs - condition: > - ((open_read or open_directory) and - (user_ssh_directory or fd.name startswith /root/.ssh) and - not user_known_read_ssh_information_activities and - not proc.name in (ssh_binaries)) - enabled: false - output: > - ssh-related file/directory read by non-ssh program (user=%user.name user_loginuid=%user.loginuid - command=%proc.cmdline pid=%proc.pid file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline container_id=%container.id image=%container.image.repository) - priority: ERROR - tags: [host, container, filesystem, mitre_discovery, T1005] - -- list: safe_etc_dirs - items: [/etc/cassandra, /etc/ssl/certs/java, /etc/logstash, /etc/nginx/conf.d, /etc/container_environment, /etc/hrmconfig, /etc/fluent/configs.d. /etc/alertmanager] - -- macro: fluentd_writing_conf_files - condition: (proc.name=start-fluentd and fd.name in (/etc/fluent/fluent.conf, /etc/td-agent/td-agent.conf)) - -- macro: qualys_writing_conf_files - condition: (proc.name=qualys-cloud-ag and fd.name=/etc/qualys/cloud-agent/qagent-log.conf) - -- macro: git_writing_nssdb - condition: (proc.name=git-remote-http and fd.directory=/etc/pki/nssdb) - -- macro: plesk_writing_keys - condition: (proc.name in (plesk_binaries) and fd.name startswith /etc/sw/keys) - -- macro: plesk_install_writing_apache_conf - condition: (proc.cmdline startswith "bash -hB /usr/lib/plesk-9.0/services/webserver.apache configure" - and fd.name="/etc/apache2/apache2.conf.tmp") - -- macro: plesk_running_mktemp - condition: (proc.name=mktemp and proc.aname[3] in (plesk_binaries)) - -- macro: networkmanager_writing_resolv_conf - condition: proc.aname[2]=nm-dispatcher and fd.name=/etc/resolv.conf - -- macro: add_shell_writing_shells_tmp - condition: (proc.name=add-shell and fd.name=/etc/shells.tmp) - -- macro: duply_writing_exclude_files - condition: (proc.name=touch and proc.pcmdline startswith "bash /usr/bin/duply" and fd.name startswith "/etc/duply") - -- macro: xmlcatalog_writing_files - condition: (proc.name=update-xmlcatal and fd.directory=/etc/xml) - -- macro: datadog_writing_conf - condition: ((proc.cmdline startswith "python /opt/datadog-agent" or - proc.cmdline startswith "entrypoint.sh /entrypoint.sh datadog start" or - proc.cmdline startswith "agent.py /opt/datadog-agent") - and fd.name startswith "/etc/dd-agent") - -- macro: rancher_writing_conf - condition: ((proc.name in (healthcheck, lb-controller, rancher-dns)) and - (container.image.repository contains "rancher/healthcheck" or - container.image.repository contains "rancher/lb-service-haproxy" or - container.image.repository contains "rancher/dns") and - (fd.name startswith "/etc/haproxy" or fd.name startswith "/etc/rancher-dns")) - -- macro: rancher_writing_root - condition: (proc.name=rancher-metadat and - (container.image.repository contains "rancher/metadata" or container.image.repository contains "rancher/lb-service-haproxy") and - fd.name startswith "/answers.json") - -- macro: checkpoint_writing_state - condition: (proc.name=checkpoint and - container.image.repository contains "coreos/pod-checkpointer" and - fd.name startswith "/etc/kubernetes") - -- macro: jboss_in_container_writing_passwd - condition: > - ((proc.cmdline="run-java.sh /opt/jboss/container/java/run/run-java.sh" - or proc.cmdline="run-java.sh /opt/run-java/run-java.sh") - and container - and fd.name=/etc/passwd) - -- macro: curl_writing_pki_db - condition: (proc.name=curl and fd.directory=/etc/pki/nssdb) - -- macro: haproxy_writing_conf - condition: ((proc.name in (update-haproxy-,haproxy_reload.) or proc.pname in (update-haproxy-,haproxy_reload,haproxy_reload.)) - and (fd.name=/etc/openvpn/client.map or fd.name startswith /etc/haproxy)) - -- macro: java_writing_conf - condition: (proc.name=java and fd.name=/etc/.java/.systemPrefs/.system.lock) - -- macro: rabbitmq_writing_conf - condition: (proc.name=rabbitmq-server and fd.directory=/etc/rabbitmq) - -- macro: rook_writing_conf - condition: (proc.name=toolbox.sh and container.image.repository=rook/toolbox - and fd.directory=/etc/ceph) - -- macro: httpd_writing_conf_logs - condition: (proc.name=httpd and fd.name startswith /etc/httpd/) - -- macro: mysql_writing_conf - condition: > - ((proc.name in (start-mysql.sh, run-mysqld) or proc.pname=start-mysql.sh) and - (fd.name startswith /etc/mysql or fd.directory=/etc/my.cnf.d)) - -- macro: redis_writing_conf - condition: > - (proc.name in (run-redis, redis-launcher.) and (fd.name=/etc/redis.conf or fd.name startswith /etc/redis)) - -- macro: openvpn_writing_conf - condition: (proc.name in (openvpn,openvpn-entrypo) and fd.name startswith /etc/openvpn) - -- macro: php_handlers_writing_conf - condition: (proc.name=php_handlers_co and fd.name=/etc/psa/php_versions.json) - -- macro: sed_writing_temp_file - condition: > - ((proc.aname[3]=cron_start.sh and fd.name startswith /etc/security/sed) or - (proc.name=sed and (fd.name startswith /etc/apt/sources.list.d/sed or - fd.name startswith /etc/apt/sed or - fd.name startswith /etc/apt/apt.conf.d/sed))) - -- macro: cron_start_writing_pam_env - condition: (proc.cmdline="bash /usr/sbin/start-cron" and fd.name=/etc/security/pam_env.conf) - -# In some cases dpkg-reconfigur runs commands that modify /etc. Not -# putting the full set of package management programs yet. -- macro: dpkg_scripting - condition: (proc.aname[2] in (dpkg-reconfigur, dpkg-preconfigu)) - -- macro: ufw_writing_conf - condition: (proc.name=ufw and fd.directory=/etc/ufw) - -- macro: calico_writing_conf - condition: > - (((proc.name = calico-node) or - (container.image.repository=gcr.io/projectcalico-org/node and proc.name in (start_runit, cp)) or - (container.image.repository=gcr.io/projectcalico-org/cni and proc.name=sed)) - and fd.name startswith /etc/calico) - -- macro: prometheus_conf_writing_conf - condition: (proc.name=prometheus-conf and fd.name startswith /etc/prometheus/config_out) - -- macro: openshift_writing_conf - condition: (proc.name=oc and fd.name startswith /etc/origin/node) - -- macro: keepalived_writing_conf - condition: (proc.name in (keepalived, kube-keepalived) and fd.name=/etc/keepalived/keepalived.conf) - -- macro: etcd_manager_updating_dns - condition: (container and proc.name=etcd-manager and fd.name=/etc/hosts) - -- macro: automount_using_mtab - condition: (proc.pname = automount and fd.name startswith /etc/mtab) - -- macro: mcafee_writing_cma_d - condition: (proc.name=macompatsvc and fd.directory=/etc/cma.d) - -- macro: avinetworks_supervisor_writing_ssh - condition: > - (proc.cmdline="se_supervisor.p /opt/avi/scripts/se_supervisor.py -d" and - (fd.name startswith /etc/ssh/known_host_ or - fd.name startswith /etc/ssh/ssh_monitor_config_ or - fd.name startswith /etc/ssh/ssh_config_)) - -- macro: multipath_writing_conf - condition: (proc.name = multipath and fd.name startswith /etc/multipath/) - -# Add conditions to this macro (probably in a separate file, -# overwriting this macro) to allow for specific combinations of -# programs writing below specific directories below -# /etc. fluentd_writing_conf_files is a good example to follow, as it -# specifies both the program doing the writing as well as the specific -# files it is allowed to modify. -# -# In this file, it just takes one of the programs in the base macro -# and repeats it. - -- macro: user_known_write_etc_conditions - condition: proc.name=confd - -# This is a placeholder for user to extend the whitelist for write below etc rule -- macro: user_known_write_below_etc_activities - condition: (never_true) - -- macro: calico_node - condition: (container.image.repository endswith calico/node and proc.name=calico-node) - -- macro: write_etc_common - condition: > - etc_dir and evt.dir = < and open_write - and proc_name_exists - and not proc.name in (passwd_binaries, shadowutils_binaries, sysdigcloud_binaries, - package_mgmt_binaries, ssl_mgmt_binaries, dhcp_binaries, - dev_creation_binaries, shell_mgmt_binaries, - mail_config_binaries, - sshkit_script_binaries, - ldconfig.real, ldconfig, confd, gpg, insserv, - apparmor_parser, update-mime, tzdata.config, tzdata.postinst, - systemd, systemd-machine, systemd-sysuser, - debconf-show, rollerd, bind9.postinst, sv, - gen_resolvconf., update-ca-certi, certbot, runsv, - qualys-cloud-ag, locales.postins, nomachine_binaries, - adclient, certutil, crlutil, pam-auth-update, parallels_insta, - openshift-launc, update-rc.d, puppet, falcoctl) - and not (container and proc.cmdline in ("cp /run/secrets/kubernetes.io/serviceaccount/ca.crt /etc/pki/ca-trust/source/anchors/openshift-ca.crt")) - and not proc.pname in (sysdigcloud_binaries, mail_config_binaries, hddtemp.postins, sshkit_script_binaries, locales.postins, deb_binaries, dhcp_binaries) - and not fd.name pmatch (safe_etc_dirs) - and not fd.name in (/etc/container_environment.sh, /etc/container_environment.json, /etc/motd, /etc/motd.svc) - and not sed_temporary_file - and not exe_running_docker_save - and not ansible_running_python - and not python_running_denyhosts - and not fluentd_writing_conf_files - and not user_known_write_etc_conditions - and not run_by_centrify - and not run_by_adclient - and not qualys_writing_conf_files - and not git_writing_nssdb - and not plesk_writing_keys - and not plesk_install_writing_apache_conf - and not plesk_running_mktemp - and not networkmanager_writing_resolv_conf - and not run_by_chef - and not add_shell_writing_shells_tmp - and not duply_writing_exclude_files - and not xmlcatalog_writing_files - and not parent_supervise_running_multilog - and not supervise_writing_status - and not pki_realm_writing_realms - and not htpasswd_writing_passwd - and not lvprogs_writing_conf - and not ovsdb_writing_openvswitch - and not datadog_writing_conf - and not curl_writing_pki_db - and not haproxy_writing_conf - and not java_writing_conf - and not dpkg_scripting - and not parent_ucf_writing_conf - and not rabbitmq_writing_conf - and not rook_writing_conf - and not php_handlers_writing_conf - and not sed_writing_temp_file - and not cron_start_writing_pam_env - and not httpd_writing_conf_logs - and not mysql_writing_conf - and not openvpn_writing_conf - and not consul_template_writing_conf - and not countly_writing_nginx_conf - and not ms_oms_writing_conf - and not ms_scx_writing_conf - and not azure_scripts_writing_conf - and not azure_networkwatcher_writing_conf - and not couchdb_writing_conf - and not update_texmf_writing_conf - and not slapadd_writing_conf - and not symantec_writing_conf - and not liveupdate_writing_conf - and not sosreport_writing_files - and not selinux_writing_conf - and not veritas_writing_config - and not nginx_writing_conf - and not nginx_writing_certs - and not chef_client_writing_conf - and not centrify_writing_krb - and not sssd_writing_krb - and not cockpit_writing_conf - and not ipsec_writing_conf - and not httpd_writing_ssl_conf - and not userhelper_writing_etc_security - and not pkgmgmt_progs_writing_pki - and not update_ca_trust_writing_pki - and not brandbot_writing_os_release - and not redis_writing_conf - and not openldap_writing_conf - and not ucpagent_writing_conf - and not iscsi_writing_conf - and not istio_writing_conf - and not ufw_writing_conf - and not calico_writing_conf - and not calico_writing_envvars - and not prometheus_conf_writing_conf - and not openshift_writing_conf - and not keepalived_writing_conf - and not rancher_writing_conf - and not checkpoint_writing_state - and not jboss_in_container_writing_passwd - and not etcd_manager_updating_dns - and not user_known_write_below_etc_activities - and not automount_using_mtab - and not mcafee_writing_cma_d - and not avinetworks_supervisor_writing_ssh - and not multipath_writing_conf - and not calico_node - -- rule: Write below etc - desc: an attempt to write to any file below /etc - condition: write_etc_common - output: "File below /etc opened for writing (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid parent=%proc.pname pcmdline=%proc.pcmdline file=%fd.name program=%proc.name gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] container_id=%container.id image=%container.image.repository)" - priority: ERROR - tags: [host, container, filesystem, mitre_persistence, T1098] - -- list: known_root_files - items: [/root/.monit.state, /root/.auth_tokens, /root/.bash_history, /root/.ash_history, /root/.aws/credentials, - /root/.viminfo.tmp, /root/.lesshst, /root/.bzr.log, /root/.gitconfig.lock, /root/.babel.json, /root/.localstack, - /root/.node_repl_history, /root/.mongorc.js, /root/.dbshell, /root/.augeas/history, /root/.rnd, /root/.wget-hsts, /health, /exec.fifo] - -- list: known_root_directories - items: [/root/.oracle_jre_usage, /root/.ssh, /root/.subversion, /root/.nami] - -- macro: known_root_conditions - condition: (fd.name startswith /root/orcexec. - or fd.name startswith /root/.m2 - or fd.name startswith /root/.npm - or fd.name startswith /root/.pki - or fd.name startswith /root/.ivy2 - or fd.name startswith /root/.config/Cypress - or fd.name startswith /root/.config/pulse - or fd.name startswith /root/.config/configstore - or fd.name startswith /root/jenkins/workspace - or fd.name startswith /root/.jenkins - or fd.name startswith /root/.cache - or fd.name startswith /root/.sbt - or fd.name startswith /root/.java - or fd.name startswith /root/.glide - or fd.name startswith /root/.sonar - or fd.name startswith /root/.v8flag - or fd.name startswith /root/infaagent - or fd.name startswith /root/.local/lib/python - or fd.name startswith /root/.pm2 - or fd.name startswith /root/.gnupg - or fd.name startswith /root/.pgpass - or fd.name startswith /root/.theano - or fd.name startswith /root/.gradle - or fd.name startswith /root/.android - or fd.name startswith /root/.ansible - or fd.name startswith /root/.crashlytics - or fd.name startswith /root/.dbus - or fd.name startswith /root/.composer - or fd.name startswith /root/.gconf - or fd.name startswith /root/.nv - or fd.name startswith /root/.local/share/jupyter - or fd.name startswith /root/oradiag_root - or fd.name startswith /root/workspace - or fd.name startswith /root/jvm - or fd.name startswith /root/.node-gyp) - -# Add conditions to this macro (probably in a separate file, -# overwriting this macro) to allow for specific combinations of -# programs writing below specific directories below -# / or /root. -# -# In this file, it just takes one of the condition in the base macro -# and repeats it. -- macro: user_known_write_root_conditions - condition: fd.name=/root/.bash_history - -# This is a placeholder for user to extend the whitelist for write below root rule -- macro: user_known_write_below_root_activities - condition: (never_true) - -- macro: runc_writing_exec_fifo - condition: (proc.cmdline="runc:[1:CHILD] init" and fd.name=/exec.fifo) - -- macro: runc_writing_var_lib_docker - condition: (proc.cmdline="runc:[1:CHILD] init" and evt.arg.filename startswith /var/lib/docker) - -- macro: mysqlsh_writing_state - condition: (proc.name=mysqlsh and fd.directory=/root/.mysqlsh) - -- rule: Write below root - desc: an attempt to write to any file directly below / or /root - condition: > - root_dir and evt.dir = < and open_write - and proc_name_exists - and not fd.name in (known_root_files) - and not fd.directory pmatch (known_root_directories) - and not exe_running_docker_save - and not gugent_writing_guestagent_log - and not dse_writing_tmp - and not zap_writing_state - and not airflow_writing_state - and not rpm_writing_root_rpmdb - and not maven_writing_groovy - and not chef_writing_conf - and not kubectl_writing_state - and not cassandra_writing_state - and not galley_writing_state - and not calico_writing_state - and not rancher_writing_root - and not runc_writing_exec_fifo - and not mysqlsh_writing_state - and not known_root_conditions - and not user_known_write_root_conditions - and not user_known_write_below_root_activities - output: "File below / or /root opened for writing (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid parent=%proc.pname file=%fd.name program=%proc.name container_id=%container.id image=%container.image.repository)" - priority: ERROR - tags: [host, container, filesystem, mitre_persistence, TA0003] + tags: [maturity_stable, host, container, filesystem, mitre_credential_access, T1555] - macro: cmp_cp_by_passwd - condition: proc.name in (cmp, cp) and proc.pname in (passwd, run-parts) + condition: (proc.name in (cmp, cp) and proc.pname in (passwd, run-parts)) - macro: user_known_read_sensitive_files_activities condition: (never_true) - rule: Read sensitive file trusted after startup desc: > - an attempt to read any sensitive file (e.g. files containing user/password/authentication + An attempt to read any sensitive file (e.g. files containing user/password/authentication information) by a trusted program after startup. Trusted programs might read these files - at startup to load initial state, but not afterwards. - condition: sensitive_files and open_read and server_procs and not proc_is_new and proc.name!="sshd" and not user_known_read_sensitive_files_activities - output: > - Sensitive file opened for reading by trusted program after startup (user=%user.name user_loginuid=%user.loginuid - command=%proc.cmdline pid=%proc.pid parent=%proc.pname file=%fd.name parent=%proc.pname gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository) + at startup to load initial state, but not afterwards. Can be customized as needed. + In modern containerized cloud infrastructures, accessing traditional Linux sensitive files + might be less relevant, yet it remains valuable for baseline detections. While we provide additional + rules for SSH or cloud vendor-specific credentials, you can significantly enhance your security + program by crafting custom rules for critical application credentials unique to your environment. + condition: > + open_read + and sensitive_files + and server_procs + and not proc_is_new + and proc.name!="sshd" + and not user_known_read_sensitive_files_activities + output: Sensitive file opened for reading by trusted program after startup (file=%fd.name pcmdline=%proc.pcmdline gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] 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 %container.info) priority: WARNING - tags: [host, container, filesystem, mitre_credential_access, T1555, T1212, T1020, T1552, T1083] + tags: [maturity_stable, host, container, filesystem, mitre_credential_access, T1555] - list: read_sensitive_file_binaries items: [ @@ -1422,7 +376,6 @@ # # In this file, it just takes one of the macros in the base rule # and repeats it. - - macro: user_read_sensitive_file_conditions condition: cmp_cp_by_passwd @@ -1443,10 +396,15 @@ - rule: Read sensitive file untrusted desc: > - an attempt to read any sensitive file (e.g. files containing user/password/authentication - information). Exceptions are made for known trusted programs. + An attempt to read any sensitive file (e.g. files containing user/password/authentication + information). Exceptions are made for known trusted programs. Can be customized as needed. + In modern containerized cloud infrastructures, accessing traditional Linux sensitive files + might be less relevant, yet it remains valuable for baseline detections. While we provide additional + rules for SSH or cloud vendor-specific credentials, you can significantly enhance your security + program by crafting custom rules for critical application credentials unique to your environment. condition: > - sensitive_files and open_read + open_read + and sensitive_files and proc_name_exists and not proc.name in (user_mgmt_binaries, userexec_binaries, package_mgmt_binaries, cron_binaries, read_sensitive_file_binaries, shell_binaries, hids_binaries, @@ -1469,35 +427,9 @@ and not linux_bench_reading_etc_shadow and not user_known_read_sensitive_files_activities and not user_read_sensitive_file_containers - output: > - Sensitive file opened for reading by non-trusted program (user=%user.name user_loginuid=%user.loginuid program=%proc.name - command=%proc.cmdline pid=%proc.pid file=%fd.name parent=%proc.pname gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] container_id=%container.id image=%container.image.repository) + output: Sensitive file opened for reading by non-trusted program (file=%fd.name gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] 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 %container.info) priority: WARNING - tags: [host, container, filesystem, mitre_credential_access, mitre_discovery, T1555, T1212, T1020, T1552, T1083] - -- macro: amazon_linux_running_python_yum - condition: > - (proc.name = python and - proc.pcmdline = "python -m amazon_linux_extras system_motd" and - proc.cmdline startswith "python -c import yum;") - -- macro: user_known_write_rpm_database_activities - condition: (never_true) - -# Only let rpm-related programs write to the rpm database -- rule: Write below rpm database - desc: an attempt to write to the rpm database by any non-rpm related program - condition: > - fd.name startswith /var/lib/rpm and open_write - and not rpm_procs - and not ansible_running_python - and not python_running_chef - and not exe_running_docker_save - and not amazon_linux_running_python_yum - and not user_known_write_rpm_database_activities - output: "Rpm database opened for writing by a non-rpm program (command=%proc.cmdline pid=%proc.pid file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline container_id=%container.id image=%container.image.repository)" - priority: ERROR - tags: [host, container, filesystem, software_mgmt, mitre_persistence, T1072] + tags: [maturity_stable, host, container, filesystem, mitre_credential_access, T1555] - macro: postgres_running_wal_e condition: (proc.pname=postgres and (proc.cmdline startswith "sh -c envdir /etc/wal-e.d/env /usr/local/bin/wal-e" or proc.cmdline startswith "sh -c envdir \"/run/etc/wal-e.d/env\" wal-g wal-push")) @@ -1517,104 +449,13 @@ condition: (proc.aname[2]=rabbitmqctl and proc.cmdline startswith "sh -c ") - macro: run_by_appdynamics - condition: (proc.pname=java and proc.pcmdline startswith "java -jar -Dappdynamics") - -- macro: user_known_db_spawned_processes - condition: (never_true) - -- rule: DB program spawned process - desc: > - a database-server related program spawned a new process other than itself. - This shouldn\'t occur and is a follow on from some SQL injection attacks. - condition: > - proc.pname in (db_server_binaries) - and spawned_process - and not proc.name in (db_server_binaries) - and not postgres_running_wal_e - and not user_known_db_spawned_processes - output: > - Database-related program spawned process other than itself (user=%user.name user_loginuid=%user.loginuid - program=%proc.cmdline pid=%proc.pid parent=%proc.pname container_id=%container.id image=%container.image.repository exe_flags=%evt.arg.flags) - priority: NOTICE - tags: [host, container, process, database, mitre_execution, T1190] - -- macro: user_known_modify_bin_dir_activities - condition: (never_true) - -- rule: Modify binary dirs - desc: an attempt to modify any file below a set of binary directories. - condition: bin_dir_rename and modify and not package_mgmt_procs and not exe_running_docker_save and not user_known_modify_bin_dir_activities - output: > - File below known binary directory renamed/removed (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid - pcmdline=%proc.pcmdline operation=%evt.type file=%fd.name %evt.args container_id=%container.id image=%container.image.repository) - priority: ERROR - tags: [host, container, filesystem, mitre_persistence, T1222.002] - -- macro: user_known_mkdir_bin_dir_activities - condition: (never_true) - -- rule: Mkdir binary dirs - desc: an attempt to create a directory below a set of binary directories. - condition: > - mkdir - and bin_dir_mkdir - and not package_mgmt_procs - and not user_known_mkdir_bin_dir_activities - and not exe_running_docker_save - output: > - Directory below known binary directory created (user=%user.name user_loginuid=%user.loginuid - command=%proc.cmdline pid=%proc.pid directory=%evt.arg.path container_id=%container.id image=%container.image.repository) - priority: ERROR - tags: [host, container, filesystem, mitre_persistence, T1222.002] - -# This list allows for easy additions to the set of commands allowed -# to change thread namespace without having to copy and override the -# entire change thread namespace rule. -- list: user_known_change_thread_namespace_binaries - items: [crio, multus] - -- macro: user_known_change_thread_namespace_activities - condition: (never_true) - -- list: network_plugin_binaries - items: [aws-cni, azure-vnet] - -- macro: weaveworks_scope - condition: (container.image.repository endswith weaveworks/scope and proc.name=scope) - -- rule: Change thread namespace - desc: > - an attempt to change a program/thread\'s namespace (commonly done - as a part of creating a container) by calling setns. - condition: > - evt.type=setns and evt.dir=< - and proc_name_exists - and not (container.id=host and proc.name in (docker_binaries, k8s_binaries, lxd_binaries, nsenter)) - and not proc.name in (sysdigcloud_binaries, sysdig, calico, oci-umount, cilium-cni, network_plugin_binaries) - and not proc.name in (user_known_change_thread_namespace_binaries) - and not proc.name startswith "runc" - and not proc.cmdline startswith "containerd" - and not proc.pname in (sysdigcloud_binaries, hyperkube, kubelet, protokube, dockerd, tini, aws) - and not java_running_sdjagent - and not kubelet_running_loopback - and not rancher_agent - and not rancher_network_manager - and not calico_node - and not weaveworks_scope - and not user_known_change_thread_namespace_activities - enabled: false - output: > - Namespace change (setns) by unexpected program (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid - parent=%proc.pname %container.info container_id=%container.id image=%container.image.repository:%container.image.tag) - priority: NOTICE - tags: [host, container, process, mitre_privilege_escalation, mitre_lateral_movement, T1611] + condition: (proc.pexe endswith java and proc.pcmdline contains " -jar -Dappdynamics") # The binaries in this list and their descendents are *not* allowed # spawn shells. This includes the binaries spawning shells directly as # well as indirectly. For example, apache -> php/perl for # mod_{php,perl} -> some shell is also not allowed, because the shell # has apache as an ancestor. - - list: protected_shell_spawning_binaries items: [ http_server_binaries, db_server_binaries, nosql_server_binaries, mail_binaries, @@ -1622,31 +463,31 @@ ] - macro: parent_java_running_zookeeper - condition: (proc.pname=java and proc.pcmdline contains org.apache.zookeeper.server) + condition: (proc.pexe endswith java and proc.pcmdline contains org.apache.zookeeper.server) - macro: parent_java_running_kafka - condition: (proc.pname=java and proc.pcmdline contains kafka.Kafka) + condition: (proc.pexe endswith java and proc.pcmdline contains kafka.Kafka) - macro: parent_java_running_elasticsearch - condition: (proc.pname=java and proc.pcmdline contains org.elasticsearch.bootstrap.Elasticsearch) + condition: (proc.pexe endswith java and proc.pcmdline contains org.elasticsearch.bootstrap.Elasticsearch) - macro: parent_java_running_activemq - condition: (proc.pname=java and proc.pcmdline contains activemq.jar) + condition: (proc.pexe endswith java and proc.pcmdline contains activemq.jar) - macro: parent_java_running_cassandra - condition: (proc.pname=java and (proc.pcmdline contains "-Dcassandra.config.loader" or proc.pcmdline contains org.apache.cassandra.service.CassandraDaemon)) + condition: (proc.pexe endswith java and (proc.pcmdline contains "-Dcassandra.config.loader" or proc.pcmdline contains org.apache.cassandra.service.CassandraDaemon)) - macro: parent_java_running_jboss_wildfly - condition: (proc.pname=java and proc.pcmdline contains org.jboss) + condition: (proc.pexe endswith java and proc.pcmdline contains org.jboss) - macro: parent_java_running_glassfish - condition: (proc.pname=java and proc.pcmdline contains com.sun.enterprise.glassfish) + condition: (proc.pexe endswith java and proc.pcmdline contains com.sun.enterprise.glassfish) - macro: parent_java_running_hadoop - condition: (proc.pname=java and proc.pcmdline contains org.apache.hadoop) + condition: (proc.pexe endswith java and proc.pcmdline contains org.apache.hadoop) - macro: parent_java_running_datastax - condition: (proc.pname=java and proc.pcmdline contains com.datastax) + condition: (proc.pexe endswith java and proc.pcmdline contains com.datastax) - macro: nginx_starting_nginx condition: (proc.pname=nginx and proc.cmdline contains "/usr/sbin/nginx -c /etc/nginx/nginx.conf") @@ -1693,7 +534,7 @@ # # Like for node, we make this case opt-in. - macro: possibly_parent_java_running_tomcat - condition: (never_true and proc.pname=java and proc.pcmdline contains org.apache.catalina.startup.Bootstrap) + condition: (never_true and proc.pexe endswith java and proc.pcmdline contains org.apache.catalina.startup.Bootstrap) - macro: protected_shell_spawner condition: > @@ -1718,7 +559,16 @@ # (the ./run and ./finish scripts), but the processes runsv can not # spawn shells. - rule: Run shell untrusted - desc: an attempt to spawn a shell below a non-shell application. Specific applications are monitored. + desc: > + An attempt to spawn a shell below a non-shell application. The non-shell applications that are monitored are + defined in the protected_shell_spawner macro, with protected_shell_spawning_binaries being the list you can + easily customize. For Java parent processes, please note that Java often has a custom process name. Therefore, + rely more on proc.exe to define Java applications. This rule can be noisier, as you can see in the exhaustive + existing tuning. However, given it is very behavior-driven and broad, it is universally relevant to catch + general Remote Code Execution (RCE). Allocate time to tune this rule for your use cases and reduce noise. + Tuning suggestions include looking at the duration of the parent process (proc.ppid.duration) to define your + long-running app processes. Checking for newer fields such as proc.vpgid.name and proc.vpgid.exe instead of the + direct parent process being a non-shell application could make the rule more robust. condition: > spawned_process and shell_procs @@ -1749,74 +599,9 @@ and not rabbitmqctl_running_scripts and not run_by_appdynamics and not user_shell_container_exclusions - output: > - Shell spawned by untrusted binary (user=%user.name user_loginuid=%user.loginuid shell=%proc.name parent=%proc.pname - cmdline=%proc.cmdline pid=%proc.pid pcmdline=%proc.pcmdline gparent=%proc.aname[2] ggparent=%proc.aname[3] - aname[4]=%proc.aname[4] aname[5]=%proc.aname[5] aname[6]=%proc.aname[6] aname[7]=%proc.aname[7] container_id=%container.id image=%container.image.repository exe_flags=%evt.arg.flags) - priority: DEBUG - tags: [host, container, process, shell, mitre_execution, T1059.004] - -- macro: allowed_openshift_registry_root - condition: > - (container.image.repository startswith openshift3/ or - container.image.repository startswith registry.redhat.io/openshift3/ or - container.image.repository startswith registry.access.redhat.com/openshift3/) - -# Source: https://docs.openshift.com/enterprise/3.2/install_config/install/disconnected_install.html -- macro: openshift_image - condition: > - (allowed_openshift_registry_root and - (container.image.repository endswith /logging-deployment or - container.image.repository endswith /logging-elasticsearch or - container.image.repository endswith /logging-kibana or - container.image.repository endswith /logging-fluentd or - container.image.repository endswith /logging-auth-proxy or - container.image.repository endswith /metrics-deployer or - container.image.repository endswith /metrics-hawkular-metrics or - container.image.repository endswith /metrics-cassandra or - container.image.repository endswith /metrics-heapster or - container.image.repository endswith /ose-haproxy-router or - container.image.repository endswith /ose-deployer or - container.image.repository endswith /ose-sti-builder or - container.image.repository endswith /ose-docker-builder or - container.image.repository endswith /ose-pod or - container.image.repository endswith /ose-node or - container.image.repository endswith /ose-docker-registry or - container.image.repository endswith /prometheus-node-exporter or - container.image.repository endswith /image-inspector)) - -- list: redhat_io_images_privileged - items: [registry.redhat.io/openshift-logging/fluentd-rhel8, registry.redhat.io/openshift4/ose-csi-node-driver-registrar, registry.redhat.io/openshift4/ose-kubernetes-nmstate-handler-rhel8, registry.redhat.io/openshift4/ose-local-storage-diskmaker] - -- macro: redhat_image - condition: > - (container.image.repository in (redhat_io_images_privileged)) - -# https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html -# official AWS EKS registry list. AWS has different ECR repo per region -- macro: allowed_aws_ecr_registry_root_for_eks - condition: > - (container.image.repository startswith "602401143452.dkr.ecr" or - container.image.repository startswith "877085696533.dkr.ecr" or - container.image.repository startswith "800184023465.dkr.ecr" or - container.image.repository startswith "918309763551.dkr.ecr" or - container.image.repository startswith "961992271922.dkr.ecr" or - container.image.repository startswith "590381155156.dkr.ecr" or - container.image.repository startswith "558608220178.dkr.ecr" or - container.image.repository startswith "151742754352.dkr.ecr" or - container.image.repository startswith "013241004608.dkr.ecr") - - -- macro: aws_eks_core_images - condition: > - (allowed_aws_ecr_registry_root_for_eks and - (container.image.repository endswith ".amazonaws.com/amazon-k8s-cni" or - container.image.repository endswith ".amazonaws.com/eks/kube-proxy")) - - -- macro: aws_eks_image_sensitive_mount - condition: > - (allowed_aws_ecr_registry_root_for_eks and container.image.repository endswith ".amazonaws.com/amazon-k8s-cni") + output: Shell spawned by untrusted binary (parent_exe=%proc.pexe parent_exepath=%proc.pexepath pcmdline=%proc.pcmdline gparent=%proc.aname[2] ggparent=%proc.aname[3] aname[4]=%proc.aname[4] aname[5]=%proc.aname[5] aname[6]=%proc.aname[6] aname[7]=%proc.aname[7] 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 %container.info) + priority: NOTICE + tags: [maturity_stable, host, container, process, shell, mitre_execution, T1059.004] # These images are allowed both to run with --privileged and to mount # sensitive paths from the host filesystem. @@ -1828,20 +613,6 @@ - list: trusted_images items: [] -# Add conditions to this macro (probably in a separate file, -# overwriting this macro) to specify additional containers that are -# trusted and therefore allowed to run privileged *and* with sensitive -# mounts. -# -# Like trusted_images, this is deprecated in favor of -# user_privileged_containers and user_sensitive_mount_containers and -# is only provided for backwards compatibility. -# -# In this file, it just takes one of the images in trusted_containers -# and repeats it. -- macro: user_trusted_containers - condition: (never_true) - - list: sematext_images items: [docker.io/sematext/sematext-agent-docker, docker.io/sematext/agent, docker.io/sematext/logagent, registry.access.redhat.com/sematext/sematext-agent-docker, @@ -1896,110 +667,6 @@ mcr.microsoft.com/oss/kubernetes/kube-proxy ] -- macro: falco_privileged_containers - condition: (openshift_image or - user_trusted_containers or - aws_eks_core_images or - container.image.repository in (trusted_images) or - container.image.repository in (falco_privileged_images) or - container.image.repository startswith istio/proxy_ or - container.image.repository startswith quay.io/sysdig/) - -# Add conditions to this macro (probably in a separate file, -# overwriting this macro) to specify additional containers that are -# allowed to run privileged -# -# In this file, it just takes one of the images in falco_privileged_images -# and repeats it. -- macro: user_privileged_containers - condition: (never_true) - -# These container images are allowed to mount sensitive paths from the -# host filesystem. -- list: falco_sensitive_mount_images - items: [ - falco_containers, - docker.io/sysdig/sysdig, sysdig/sysdig, - gcr.io/google_containers/hyperkube, - gcr.io/google_containers/kube-proxy, docker.io/calico/node, - docker.io/rook/toolbox, docker.io/cloudnativelabs/kube-router, docker.io/consul, - docker.io/datadog/docker-dd-agent, docker.io/datadog/agent, docker.io/docker/ucp-agent, docker.io/gliderlabs/logspout, - docker.io/netdata/netdata, docker.io/google/cadvisor, docker.io/prom/node-exporter, - amazon/amazon-ecs-agent, prom/node-exporter, amazon/cloudwatch-agent - ] - -- macro: falco_sensitive_mount_containers - condition: (user_trusted_containers or - aws_eks_image_sensitive_mount or - container.image.repository in (trusted_images) or - container.image.repository in (falco_sensitive_mount_images) or - container.image.repository startswith quay.io/sysdig/ or - container.image.repository=k8scloudprovider/cinder-csi-plugin) - -# Add conditions to this macro (probably in a separate file, -# overwriting this macro) to specify additional containers that are -# allowed to perform sensitive mounts. -# -# In this file, it just takes one of the images in falco_sensitive_mount_images -# and repeats it. -- macro: user_sensitive_mount_containers - condition: (never_true) - -- rule: Launch Privileged Container - desc: Detect the initial process started in a privileged container. Exceptions are made for known trusted images. - condition: > - container_started and container - and container.privileged=true - and not falco_privileged_containers - and not user_privileged_containers - and not redhat_image - output: Privileged container started (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag) - priority: INFO - tags: [container, cis, mitre_privilege_escalation, mitre_lateral_movement, T1610] - -# These capabilities were used in the past to escape from containers -- macro: excessively_capable_container - condition: > - (thread.cap_permitted contains CAP_SYS_ADMIN - or thread.cap_permitted contains CAP_SYS_MODULE - or thread.cap_permitted contains CAP_SYS_RAWIO - or thread.cap_permitted contains CAP_SYS_PTRACE - or thread.cap_permitted contains CAP_SYS_BOOT - or thread.cap_permitted contains CAP_SYSLOG - or thread.cap_permitted contains CAP_DAC_READ_SEARCH - or thread.cap_permitted contains CAP_NET_ADMIN - or thread.cap_permitted contains CAP_BPF) - -- rule: Launch Excessively Capable Container - desc: Detect container started with a powerful set of capabilities. Exceptions are made for known trusted images. - condition: > - container_started and container - and excessively_capable_container - and not falco_privileged_containers - and not user_privileged_containers - output: Excessively capable container started (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag cap_permitted=%thread.cap_permitted) - priority: INFO - tags: [container, cis, mitre_privilege_escalation, mitre_lateral_movement, T1610] - - -# For now, only considering a full mount of /etc as -# sensitive. Ideally, this would also consider all subdirectories -# below /etc as well, but the globbing mechanism -# doesn't allow exclusions of a full pattern, only single characters. -- macro: sensitive_mount - condition: (container.mount.dest[/proc*] != "N/A" or - container.mount.dest[/var/run/docker.sock] != "N/A" or - container.mount.dest[/var/run/crio/crio.sock] != "N/A" or - container.mount.dest[/run/containerd/containerd.sock] != "N/A" or - container.mount.dest[/var/lib/kubelet] != "N/A" or - container.mount.dest[/var/lib/kubelet/pki] != "N/A" or - container.mount.dest[/] != "N/A" or - container.mount.dest[/home/admin] != "N/A" or - container.mount.dest[/etc] != "N/A" or - container.mount.dest[/etc/kubernetes] != "N/A" or - container.mount.dest[/etc/kubernetes/manifests] != "N/A" or - container.mount.dest[/root*] != "N/A") - # The steps libcontainer performs to set up the root program for a container are: # - clone + exec self to a program runc:[0:PARENT] # - clone a program runc:[1:CHILD] which sets up all the namespaces @@ -2010,41 +677,8 @@ # already exited, or might still be around. So we handle both. # We also let runc:[1:CHILD] count as the parent process, which can occur # when we lose events and lose track of state. - - macro: container_entrypoint - condition: (not proc.pname exists or proc.pname in (runc:[0:PARENT], runc:[1:CHILD], runc, docker-runc, exe, docker-runc-cur)) - -- rule: Launch Sensitive Mount Container - desc: > - Detect the initial process started by a container that has a mount from a sensitive host directory - (i.e. /proc). Exceptions are made for known trusted images. - condition: > - container_started and container - and sensitive_mount - and not falco_sensitive_mount_containers - and not user_sensitive_mount_containers - output: Container with sensitive mount started (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag mounts=%container.mounts) - priority: INFO - tags: [container, cis, mitre_lateral_movement, T1610] - -# In a local/user rules file, you could override this macro to -# explicitly enumerate the container images that you want to run in -# your environment. In this main falco rules file, there isn't any way -# to know all the containers that can run, so any container is -# allowed, by using a filter that is guaranteed to evaluate to true. -# In the overridden macro, the condition would look something like -# (container.image.repository = vendor/container-1 or -# container.image.repository = vendor/container-2 or ...) -- macro: allowed_containers - condition: (container.id exists) - -- rule: Launch Disallowed Container - desc: > - Detect the initial process started by a container that is not in a list of allowed containers. - condition: container_started and container and not allowed_containers - output: Container started and not in allowed list (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag) - priority: WARNING - tags: [container, mitre_lateral_movement, T1610] + condition: (not proc.pname exists or proc.pname in (runc:[0:PARENT], runc:[1:CHILD], runc, docker-runc, exe, docker-runc-cur, containerd-shim, systemd, crio)) - macro: user_known_system_user_login condition: (never_true) @@ -2053,13 +687,24 @@ # - condition: evt.type != switch and user.name = root and proc.name != sshd and interactive # output: "Interactive root (%user.name %proc.name %evt.dir %evt.type %evt.args %fd.name)" # priority: WARNING - - rule: System user interactive - desc: an attempt to run interactive commands by a system (i.e. non-login) user - condition: spawned_process and system_users and interactive and not user_known_system_user_login - output: "System user ran an interactive command (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid container_id=%container.id image=%container.image.repository exe_flags=%evt.arg.flags)" + desc: > + System (e.g. non-login) users spawning new processes. Can add custom service users (e.g. apache or mysqld). + 'Interactive' is defined as new processes as descendants of an ssh session or login process. Consider further tuning + by only looking at processes in a terminal / tty (proc.tty != 0). A newer field proc.is_vpgid_leader could be of help + to distinguish if the process was "directly" executed, for instance, in a tty, or executed as a descendant process in the + same process group, which, for example, is the case when subprocesses are spawned from a script. Consider this rule + as a great template rule to monitor interactive accesses to your systems more broadly. However, such a custom rule would be + unique to your environment. The rule "Terminal shell in container" that fires when using "kubectl exec" is more Kubernetes + relevant, whereas this one could be more interesting for the underlying host. + condition: > + spawned_process + and system_users + and interactive + and not user_known_system_user_login + output: System user ran an interactive command (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 %container.info) priority: INFO - tags: [host, container, users, mitre_execution, T1059] + tags: [maturity_stable, host, container, users, mitre_execution, T1059, NIST_800-53_AC-2] # In some cases, a shell is expected to be run in a container. For example, configuration # management software may do this, which is expected. @@ -2067,23 +712,27 @@ condition: (never_true) - rule: Terminal shell in container - desc: A shell was used as the entrypoint/exec point into a container with an attached terminal. + desc: > + A shell was used as the entrypoint/exec point into a container with an attached terminal. Parent process may have + legitimately already exited and be null (read container_entrypoint macro). Common when using "kubectl exec" in Kubernetes. + Correlate with k8saudit exec logs if possible to find user or serviceaccount token used (fuzzy correlation by namespace and pod name). + Rather than considering it a standalone rule, it may be best used as generic auditing rule while examining other triggered + rules in this container/tty. condition: > - spawned_process and container - and shell_procs and proc.tty != 0 + spawned_process + and container + and shell_procs + and proc.tty != 0 and container_entrypoint and not user_expected_terminal_shell_in_container_conditions - output: > - A shell was spawned in a container with an attached terminal (user=%user.name user_loginuid=%user.loginuid %container.info - shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline pid=%proc.pid terminal=%proc.tty container_id=%container.id image=%container.image.repository exe_flags=%evt.arg.flags) + output: A shell was spawned in a container with an attached terminal (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 %container.info) priority: NOTICE - tags: [container, shell, mitre_execution, T1059] + tags: [maturity_stable, container, shell, mitre_execution, T1059] # For some container types (mesos), there isn't a container image to # work with, and the container name is autogenerated, so there isn't # any stable aspect of the software to work with. In this case, we # fall back to allowing certain command lines. - - list: known_shell_spawn_cmdlines items: [ '"sh -c uname -p 2> /dev/null"', @@ -2136,287 +785,6 @@ - macro: user_shell_container_exclusions condition: (never_true) -- macro: login_doing_dns_lookup - condition: (proc.name=login and fd.l4proto=udp and fd.sport=53) - -# sockfamily ip is to exclude certain processes (like 'groups') that communicate on unix-domain sockets -# systemd can listen on ports to launch things like sshd on demand -- rule: System procs network activity - desc: any network activity performed by system binaries that are not expected to send or receive any network traffic - condition: > - (fd.sockfamily = ip and (system_procs or proc.name in (shell_binaries))) - and (inbound_outbound) - and not proc.name in (known_system_procs_network_activity_binaries) - and not login_doing_dns_lookup - and not user_expected_system_procs_network_activity_conditions - output: > - Known system binary sent/received network traffic - (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid connection=%fd.name container_id=%container.id image=%container.image.repository) - priority: NOTICE - tags: [host, container, network, mitre_exfiltration, T1059, TA0011] - -# This list allows easily whitelisting system proc names that are -# expected to communicate on the network. -- list: known_system_procs_network_activity_binaries - items: [systemd, hostid, id] - -# This macro allows specifying conditions under which a system binary -# is allowed to communicate on the network. For instance, only specific -# proc.cmdline values could be allowed to be more granular in what is -# allowed. -- macro: user_expected_system_procs_network_activity_conditions - condition: (never_true) - -# When filled in, this should look something like: -# (proc.env contains "HTTP_PROXY=http://my.http.proxy.com ") -# The trailing space is intentional so avoid matching on prefixes of -# the actual proxy. -- macro: allowed_ssh_proxy_env - condition: (always_true) - -- list: http_proxy_binaries - items: [curl, wget] - -- macro: http_proxy_procs - condition: (proc.name in (http_proxy_binaries)) - -- rule: Program run with disallowed http proxy env - desc: An attempt to run a program with a disallowed HTTP_PROXY environment variable - condition: > - spawned_process and - http_proxy_procs and - not allowed_ssh_proxy_env and - proc.env icontains HTTP_PROXY - enabled: false - output: > - Program run with disallowed HTTP_PROXY environment variable - (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid env=%proc.env parent=%proc.pname container_id=%container.id image=%container.image.repository exe_flags=%evt.arg.flags) - priority: NOTICE - tags: [host, container, users, mitre_command_and_control, T1090, T1204] - -# In some environments, any attempt by a interpreted program (perl, -# python, ruby, etc) to listen for incoming connections or perform -# outgoing connections might be suspicious. These rules are not -# enabled by default. - -- rule: Interpreted procs inbound network activity - desc: Any inbound network activity performed by any interpreted program (perl, python, ruby, etc.) - condition: > - (inbound and interpreted_procs) - enabled: false - output: > - Interpreted program received/listened for network traffic - (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid connection=%fd.name container_id=%container.id image=%container.image.repository) - priority: NOTICE - tags: [host, container, network, mitre_exfiltration, TA0011] - -- rule: Interpreted procs outbound network activity - desc: Any outbound network activity performed by any interpreted program (perl, python, ruby, etc.) - condition: > - (outbound and interpreted_procs) - enabled: false - output: > - Interpreted program performed outgoing network connection - (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid connection=%fd.name container_id=%container.id image=%container.image.repository) - priority: NOTICE - tags: [host, container, network, mitre_exfiltration, TA0011] - -- list: openvpn_udp_ports - items: [1194, 1197, 1198, 8080, 9201] - -- list: l2tp_udp_ports - items: [500, 1701, 4500, 10000] - -- list: statsd_ports - items: [8125] - -- list: ntp_ports - items: [123] - -# Some applications will connect a udp socket to an address only to -# test connectivity. Assuming the udp connect works, they will follow -# up with a tcp connect that actually sends/receives data. -# -# With that in mind, we listed a few commonly seen ports here to avoid -# some false positives. In addition, we make the main rule opt-in, so -# it's disabled by default. - -- list: test_connect_ports - items: [0, 9, 80, 3306] - -- list: expected_udp_ports - items: [53, openvpn_udp_ports, l2tp_udp_ports, statsd_ports, ntp_ports, test_connect_ports] - -- macro: expected_udp_traffic - condition: fd.port in (expected_udp_ports) - -- rule: Unexpected UDP Traffic - desc: UDP traffic not on port 53 (DNS) or other commonly used ports - condition: (inbound_outbound) and fd.l4proto=udp and not expected_udp_traffic - enabled: false - output: > - Unexpected UDP Traffic Seen - (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid connection=%fd.name proto=%fd.l4proto evt=%evt.type %evt.args container_id=%container.id image=%container.image.repository) - priority: NOTICE - tags: [host, container, network, mitre_exfiltration, TA0011] - -# With the current restriction on system calls handled by falco -# (e.g. excluding read/write/sendto/recvfrom/etc, this rule won't -# trigger). -# - rule: Ssh error in syslog -# desc: any ssh errors (failed logins, disconnects, ...) sent to syslog -# condition: syslog and ssh_error_message and evt.dir = < -# output: "sshd sent error message to syslog (error=%evt.buffer)" -# priority: WARNING - -- macro: somebody_becoming_themselves - condition: ((user.name=nobody and evt.arg.uid=nobody) or - (user.name=www-data and evt.arg.uid=www-data) or - (user.name=_apt and evt.arg.uid=_apt) or - (user.name=postfix and evt.arg.uid=postfix) or - (user.name=pki-agent and evt.arg.uid=pki-agent) or - (user.name=pki-acme and evt.arg.uid=pki-acme) or - (user.name=nfsnobody and evt.arg.uid=nfsnobody) or - (user.name=postgres and evt.arg.uid=postgres)) - -- macro: nrpe_becoming_nagios - condition: (proc.name=nrpe and evt.arg.uid=nagios) - -# In containers, the user name might be for a uid that exists in the -# container but not on the host. (See -# https://github.com/draios/sysdig/issues/954). So in that case, allow -# a setuid. -- macro: known_user_in_container - condition: (container and user.name != "N/A") - -# Add conditions to this macro (probably in a separate file, -# overwriting this macro) to allow for specific combinations of -# programs changing users by calling setuid. -# -# In this file, it just takes one of the condition in the base macro -# and repeats it. -- macro: user_known_non_sudo_setuid_conditions - condition: user.name=root - -# Disabled for now due to buysbox noise -# sshd, mail programs attempt to setuid to root even when running as non-root. Excluding here to avoid meaningless FPs -#- rule: Non sudo setuid -# desc: > -# an attempt to change users by calling setuid. sudo/su are excluded. users "root" and "nobody" -# suing to itself are also excluded, as setuid calls typically involve dropping privileges. -# condition: > -# evt.type=setuid and evt.dir=> -# and (known_user_in_container or not container) -# and not (user.name=root or user.uid=0) -# and not somebody_becoming_themselves -# and not proc.name in (known_setuid_binaries, userexec_binaries, mail_binaries, docker_binaries, -# nomachine_binaries) -# and not proc.name startswith "runc:" -# and not java_running_sdjagent -# and not nrpe_becoming_nagios -# and not user_known_non_sudo_setuid_conditions -# output: > -# Unexpected setuid call by non-sudo, non-root program (user=%user.name user_loginuid=%user.loginuid cur_uid=%user.uid parent=%proc.pname -# command=%proc.cmdline pid=%proc.pid uid=%evt.arg.uid container_id=%container.id image=%container.image.repository) -# priority: NOTICE -# tags: [host, container, users, mitre_privilege_escalation, T1548.001] - -- macro: user_known_user_management_activities - condition: (never_true) - -- macro: chage_list - condition: (proc.name=chage and (proc.cmdline contains "-l" or proc.cmdline contains "--list")) - -- rule: User mgmt binaries - desc: > - activity by any programs that can manage users, passwords, or permissions. sudo and su are excluded. - Activity in containers is also excluded--some containers create custom users on top - of a base linux distribution at startup. - Some innocuous command lines that don't actually change anything are excluded. - condition: > - spawned_process and proc.name in (user_mgmt_binaries) and - not proc.name in (su, sudo, lastlog, nologin, unix_chkpwd) and not container and - not proc.pname in (cron_binaries, systemd, systemd.postins, udev.postinst, run-parts) and - not proc.cmdline startswith "passwd -S" and - not proc.cmdline startswith "useradd -D" and - not proc.cmdline startswith "systemd --version" and - not run_by_qualys and - not run_by_sumologic_securefiles and - not run_by_yum and - not run_by_ms_oms and - not run_by_google_accounts_daemon and - not chage_list and - not user_known_user_management_activities - output: > - User management binary command run outside of container - (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid parent=%proc.pname gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] exe_flags=%evt.arg.flags) - priority: NOTICE - tags: [host, container, users, software_mgmt, mitre_persistence, T1543, T1098] - -- list: allowed_dev_files - items: [ - /dev/null, /dev/stdin, /dev/stdout, /dev/stderr, - /dev/random, /dev/urandom, /dev/console, /dev/kmsg - ] - -- macro: user_known_create_files_below_dev_activities - condition: (never_true) - -# (we may need to add additional checks against false positives, see: -# https://bugs.launchpad.net/ubuntu/+source/rkhunter/+bug/86153) -- rule: Create files below dev - desc: creating any files below /dev other than known programs that manage devices. Some rootkits hide files in /dev. - condition: > - fd.directory = /dev and - (evt.type = creat or (evt.type in (open,openat,openat2) and evt.arg.flags contains O_CREAT)) - and not proc.name in (dev_creation_binaries) - and not fd.name in (allowed_dev_files) - and not fd.name startswith /dev/tty - and not user_known_create_files_below_dev_activities - output: "File created below /dev by untrusted program (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid file=%fd.name container_id=%container.id image=%container.image.repository)" - priority: ERROR - tags: [host, container, filesystem, mitre_persistence, T1543, T1083] - - -# In a local/user rules file, you could override this macro to -# explicitly enumerate the container images that you want to allow -# access to EC2 metadata. In this main falco rules file, there isn't -# any way to know all the containers that should have access, so any -# container is allowed, by repeating the "container" macro. In the -# overridden macro, the condition would look something like -# (container.image.repository = vendor/container-1 or -# container.image.repository = vendor/container-2 or ...) -- macro: ec2_metadata_containers - condition: container - -# On EC2 instances, 169.254.169.254 is a special IP used to fetch -# metadata about the instance. It may be desirable to prevent access -# to this IP from containers. -- rule: Contact EC2 Instance Metadata Service From Container - desc: Detect attempts to contact the EC2 Instance Metadata Service from a container - condition: outbound and fd.sip="169.254.169.254" and container and not ec2_metadata_containers - output: Outbound connection to EC2 instance metadata service (command=%proc.cmdline pid=%proc.pid connection=%fd.name %container.info image=%container.image.repository:%container.image.tag) - priority: NOTICE - enabled: false - tags: [network, aws, container, mitre_discovery, T1565] - - -# This rule is not enabled by default, since this rule is for cloud environment(GCP, AWS and Azure) only. -# You can filter the container that you want to allow access to metadata by overwriting user_known_metadata_access macro. - -- macro: user_known_metadata_access - condition: (k8s.ns.name = "kube-system") - -# On GCP, AWS and Azure, 169.254.169.254 is a special IP used to fetch -# metadata about the instance. The metadata could be used to get credentials by attackers. -- rule: Contact cloud metadata service from container - desc: Detect attempts to contact the Cloud Instance Metadata Service from a container - condition: outbound and fd.sip="169.254.169.254" and container and not user_known_metadata_access - enabled: false - output: Outbound connection to cloud instance metadata service (command=%proc.cmdline pid=%proc.pid connection=%fd.name %container.info image=%container.image.repository:%container.image.tag) - priority: NOTICE - tags: [network, container, mitre_discovery, T1565] - # Containers from IBM Cloud - list: ibm_cloud_containers items: @@ -2454,118 +822,43 @@ condition: (never_true) - rule: Contact K8S API Server From Container - desc: Detect attempts to contact the K8S API Server from a container + desc: > + Detect attempts to communicate with the K8S API Server from a container by non-profiled users. Kubernetes APIs play a + pivotal role in configuring the cluster management lifecycle. Detecting potential unauthorized access to the API server + is of utmost importance. Audit your complete infrastructure and pinpoint any potential machines from which the API server + might be accessible based on your network layout. If Falco can't operate on all these machines, consider analyzing the + Kubernetes audit logs (typically drained from control nodes, and Falco offers a k8saudit plugin) as an additional data + source for detections within the control plane. condition: > - evt.type=connect and evt.dir=< and - (fd.typechar=4 or fd.typechar=6) and - container and - not k8s_containers and - k8s_api_server and - not user_known_contact_k8s_api_server_activities - output: Unexpected connection to K8s API Server from container (command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag connection=%fd.name) + evt.type=connect and evt.dir=< + and (fd.typechar=4 or fd.typechar=6) + and container + and k8s_api_server + and not k8s_containers + and not user_known_contact_k8s_api_server_activities + output: Unexpected connection to K8s API Server from container (connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto 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 %container.info) priority: NOTICE - tags: [network, k8s, container, mitre_discovery, T1565] - -# In a local/user rules file, list the container images that are -# allowed to contact NodePort services from within a container. This -# might cover cases where the K8s infrastructure itself is running -# within a container. -# -# By default, all containers are allowed to contact NodePort services. -- macro: nodeport_containers - condition: container - -- rule: Unexpected K8s NodePort Connection - desc: Detect attempts to use K8s NodePorts from a container - condition: (inbound_outbound) and fd.sport >= 30000 and fd.sport <= 32767 and container and not nodeport_containers - output: Unexpected K8s NodePort Connection (command=%proc.cmdline pid=%proc.pid connection=%fd.name container_id=%container.id image=%container.image.repository) - priority: NOTICE - tags: [network, k8s, container, mitre_persistence, T1205.001] - -- list: network_tool_binaries - items: [nc, ncat, netcat, nmap, dig, tcpdump, tshark, ngrep, telnet, mitmproxy, socat, zmap] - -- macro: network_tool_procs - condition: (proc.name in (network_tool_binaries)) - -# In a local/user rules file, create a condition that matches legitimate uses -# of a package management process inside a container. -# -# For example: -# - macro: user_known_package_manager_in_container -# condition: proc.cmdline="dpkg -l" -- macro: user_known_package_manager_in_container - condition: (never_true) - -# Container is supposed to be immutable. Package management should be done in building the image. -# TODO: Remove k8s.gcr.io reference after 01/Dec/2023 -- macro: pkg_mgmt_in_kube_proxy - condition: > - proc.cmdline startswith "update-alternat" - and (container.image.repository = "registry.k8s.io/kube-proxy" - or container.image.repository = "k8s.gcr.io/kube-proxy") - -- rule: Launch Package Management Process in Container - desc: Package management process ran inside container - condition: > - spawned_process - and container - and user.name != "_apt" - and package_mgmt_procs - and not package_mgmt_ancestor_procs - and not user_known_package_manager_in_container - and not pkg_mgmt_in_kube_proxy - output: > - Package management process launched in container (user=%user.name user_loginuid=%user.loginuid - command=%proc.cmdline pid=%proc.pid container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) - priority: ERROR - tags: [container, process, software_mgmt, mitre_persistence, T1505] + tags: [maturity_stable, container, network, k8s, mitre_discovery, T1565] - rule: Netcat Remote Code Execution in Container - desc: Netcat Program runs inside container that allows remote code execution + desc: > + Netcat Program runs inside container that allows remote code execution and may be utilized + as a part of a variety of reverse shell payload https://github.com/swisskyrepo/PayloadsAllTheThings/. + These programs are of higher relevance as they are commonly installed on UNIX-like operating systems. + Can fire in combination with the "Redirect STDOUT/STDIN to Network Connection in Container" + rule as it utilizes a different evt.type. condition: > - spawned_process and container and - ((proc.name = "nc" and (proc.args contains "-e" or proc.args contains "-c")) or - (proc.name = "ncat" and (proc.args contains "--sh-exec" or proc.args contains "--exec" or proc.args contains "-e " - or proc.args contains "-c " or proc.args contains "--lua-exec")) - ) - output: > - Netcat runs inside container that allows remote code execution (user=%user.name user_loginuid=%user.loginuid - command=%proc.cmdline pid=%proc.pid container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) + spawned_process + and container + and ((proc.name = "nc" and (proc.cmdline contains " -e" or + proc.cmdline contains " -c")) or + (proc.name = "ncat" and (proc.args contains "--sh-exec" or + proc.args contains "--exec" or proc.args contains "-e " or + proc.args contains "-c " or proc.args contains "--lua-exec")) + ) + output: Netcat runs inside container that allows remote code execution (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 %container.info) priority: WARNING - tags: [container, network, process, mitre_execution, T1059] - -- macro: user_known_network_tool_activities - condition: (never_true) - -- rule: Launch Suspicious Network Tool in Container - desc: Detect network tools launched inside container - condition: > - spawned_process and container and network_tool_procs and not user_known_network_tool_activities - output: > - Network tool launched in container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid parent_process=%proc.pname - container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) - priority: NOTICE - tags: [container, network, process, mitre_discovery, mitre_exfiltration, T1595, T1046] - -# This rule is not enabled by default, as there are legitimate use -# cases for these tools on hosts. If you want to enable it, modify the -# following macro. -- macro: consider_network_tools_on_host - condition: (never_true) - -- rule: Launch Suspicious Network Tool on Host - desc: Detect network tools launched on the host - condition: > - spawned_process and - not container and - consider_network_tools_on_host and - network_tool_procs and - not user_known_network_tool_activities - output: > - Network tool launched on host (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid parent_process=%proc.pname exe_flags=%evt.arg.flags) - priority: NOTICE - tags: [host, network, process, mitre_discovery, mitre_exfiltration, T1595, T1046] + tags: [maturity_stable, container, network, process, mitre_execution, T1059] - list: grep_binaries items: [grep, egrep, fgrep] @@ -2592,25 +885,23 @@ - rule: Search Private Keys or Passwords desc: > - Detect grep private keys or passwords activity. + Detect attempts to search for private keys or passwords using the grep or find command. This is often seen with + unsophisticated attackers, as there are many ways to access files using bash built-ins that could go unnoticed. + Regardless, this serves as a solid baseline detection that can be tailored to cover these gaps while maintaining + an acceptable noise level. condition: > - (spawned_process and - ((grep_commands and private_key_or_password) or - (proc.name = "find" and - (proc.args contains "id_rsa" or - proc.args contains "id_dsa" or - proc.args contains "id_ed25519" or - proc.args contains "id_ecdsa" - ) - )) - ) - output: > - Grep private keys or passwords activities found - (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid container_id=%container.id container_name=%container.name - image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) + spawned_process + and ((grep_commands and private_key_or_password) or + (proc.name = "find" and (proc.args contains "id_rsa" or + proc.args contains "id_dsa" or + proc.args contains "id_ed25519" or + proc.args contains "id_ecdsa" + ) + )) + output: Grep private keys or passwords activities found (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 %container.info) priority: WARNING - tags: [host, container, process, filesystem, mitre_credential_access, T1552.001] + tags: [maturity_stable, host, container, process, filesystem, mitre_credential_access, T1552.001] - list: log_directories items: [/var/log, /dev/log] @@ -2631,19 +922,26 @@ container.image.repository endswith "openshift3/ose-logging-fluentd" or container.image.repository endswith "containernetworking/azure-npm") +- macro: containerd_activities + condition: (proc.name=containerd and (fd.name startswith "/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/" or + fd.name startswith "/var/lib/containerd/tmpmounts/")) + - rule: Clear Log Activities - desc: Detect clearing of critical log files + desc: > + Detect clearing of critical access log files, typically done to erase evidence that could be attributed to an adversary's + actions. To effectively customize and operationalize this detection, check for potentially missing log file destinations + relevant to your environment, and adjust the profiled containers you wish not to be alerted on. condition: > - open_write and - access_log_files and - evt.arg.flags contains "O_TRUNC" and - not trusted_logging_images and - not allowed_clear_log_files - output: > - Log files were tampered (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid file=%fd.name container_id=%container.id image=%container.image.repository) + open_write + and access_log_files + and evt.arg.flags contains "O_TRUNC" + and not containerd_activities + and not trusted_logging_images + and not allowed_clear_log_files + output: Log files were tampered (file=%fd.name 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 %container.info) priority: WARNING - tags: [host, container, filesystem, mitre_defense_evasion, T1070] + tags: [maturity_stable, host, container, filesystem, mitre_defense_evasion, T1070, NIST_800-53_AU-10] - list: data_remove_commands items: [shred, mkfs, mke2fs] @@ -2655,680 +953,140 @@ condition: (never_true) - rule: Remove Bulk Data from Disk - desc: Detect process running to clear bulk data from disk - condition: spawned_process and clear_data_procs and not user_known_remove_data_activities - output: > - Bulk data has been removed from disk (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid file=%fd.name container_id=%container.id image=%container.image.repository exe_flags=%evt.arg.flags) + desc: > + Detect a process running to clear bulk data from disk with the intention to destroy data, possibly interrupting availability + to systems. Profile your environment and use user_known_remove_data_activities to tune this rule. + condition: > + spawned_process + and clear_data_procs + and not user_known_remove_data_activities + output: Bulk data has been removed from disk (file=%fd.name 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 %container.info) priority: WARNING - tags: [host, container, process, filesystem, mitre_persistence, T1485] - -# here `ash_history` will match both `bash_history` and `ash_history` -- macro: modify_shell_history - condition: > - (modify and ( - evt.arg.name endswith "ash_history" or - evt.arg.name endswith "zsh_history" or - evt.arg.name contains "fish_read_history" or - evt.arg.name endswith "fish_history" or - evt.arg.oldpath endswith "ash_history" or - evt.arg.oldpath endswith "zsh_history" or - evt.arg.oldpath contains "fish_read_history" or - evt.arg.oldpath endswith "fish_history" or - evt.arg.path endswith "ash_history" or - evt.arg.path endswith "zsh_history" or - evt.arg.path contains "fish_read_history" or - evt.arg.path endswith "fish_history")) - -# here `ash_history` will match both `bash_history` and `ash_history` -- macro: truncate_shell_history - condition: > - (open_write and ( - fd.name endswith "ash_history" or - fd.name endswith "zsh_history" or - fd.name contains "fish_read_history" or - fd.name endswith "fish_history") and evt.arg.flags contains "O_TRUNC") - -- macro: var_lib_docker_filepath - condition: (evt.arg.name startswith /var/lib/docker or fd.name startswith /var/lib/docker) - -- rule: Delete or rename shell history - desc: Detect shell history deletion - condition: > - (modify_shell_history or truncate_shell_history) and - not var_lib_docker_filepath and - not proc.name in (docker_binaries) - output: > - Shell history had been deleted or renamed (user=%user.name user_loginuid=%user.loginuid type=%evt.type command=%proc.cmdline pid=%proc.pid fd.name=%fd.name name=%evt.arg.name path=%evt.arg.path oldpath=%evt.arg.oldpath %container.info) - priority: - WARNING - tags: [host, container, process, filesystem, mitre_defense_evasion, T1070] - -# This rule is deprecated and will/should never be triggered. Keep it here for backport compatibility. -# Rule Delete or rename shell history is the preferred rule to use now. -- rule: Delete Bash History - desc: Detect bash history deletion - condition: > - ((spawned_process and proc.name in (shred, rm, mv) and proc.args contains "bash_history") or - (open_write and fd.name contains "bash_history" and evt.arg.flags contains "O_TRUNC")) - output: > - Shell history had been deleted or renamed (user=%user.name user_loginuid=%user.loginuid type=%evt.type command=%proc.cmdline pid=%proc.pid fd.name=%fd.name name=%evt.arg.name path=%evt.arg.path oldpath=%evt.arg.oldpath exe_flags=%evt.arg.flags %container.info) - priority: - WARNING - tags: [host, container, process, filesystem, mitre_defense_evasion, T1070] - -- list: user_known_chmod_applications - items: [hyperkube, kubelet, k3s-agent] - -# This macro should be overridden in user rules as needed. This is useful if a given application -# should not be ignored altogether with the user_known_chmod_applications list, but only in -# specific conditions. -- macro: user_known_set_setuid_or_setgid_bit_conditions - condition: (never_true) - -- rule: Set Setuid or Setgid bit - desc: > - When the setuid or setgid bits are set for an application, - this means that the application will run with the privileges of the owning user or group respectively. - Detect setuid or setgid bits set via chmod - condition: > - chmod and (evt.arg.mode contains "S_ISUID" or evt.arg.mode contains "S_ISGID") - and not proc.name in (user_known_chmod_applications) - and not exe_running_docker_save - and not user_known_set_setuid_or_setgid_bit_conditions - enabled: false - output: > - Setuid or setgid bit is set via chmod (fd=%evt.arg.fd filename=%evt.arg.filename mode=%evt.arg.mode user=%user.name user_loginuid=%user.loginuid process=%proc.name - command=%proc.cmdline pid=%proc.pid container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag) - priority: - NOTICE - tags: [host, container, process, users, mitre_persistence, T1548.001] - -- list: exclude_hidden_directories - items: [/root/.cassandra] - -# The rule is disabled by default. -- macro: user_known_create_hidden_file_activities - condition: (never_true) - -- rule: Create Hidden Files or Directories - desc: Detect hidden files or directories created - condition: > - ((modify and evt.arg.newpath contains "/.") or - (mkdir and evt.arg.path contains "/.") or - (open_write and evt.arg.flags contains "O_CREAT" and fd.name contains "/." and not fd.name pmatch (exclude_hidden_directories))) and - not user_known_create_hidden_file_activities - and not exe_running_docker_save - enabled: false - output: > - Hidden file or directory created (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid - file=%fd.name newpath=%evt.arg.newpath container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag) - priority: - NOTICE - tags: [host, container, filesystem, mitre_persistence, T1564.001] - -- list: remote_file_copy_binaries - items: [rsync, scp, sftp, dcp] - -- macro: remote_file_copy_procs - condition: (proc.name in (remote_file_copy_binaries)) - -# Users should overwrite this macro to specify conditions under which a -# Custom condition for use of remote file copy tool in container -- macro: user_known_remote_file_copy_activities - condition: (never_true) - -- rule: Launch Remote File Copy Tools in Container - desc: Detect remote file copy tools launched in container - condition: > - spawned_process - and container - and remote_file_copy_procs - and not user_known_remote_file_copy_activities - output: > - Remote file copy tool launched in container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid parent_process=%proc.pname - container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) - priority: NOTICE - tags: [container, network, process, mitre_lateral_movement, mitre_exfiltration, T1020, T1210] + tags: [maturity_stable, host, container, process, filesystem, mitre_impact, T1485] - rule: Create Symlink Over Sensitive Files - desc: Detect symlink created over sensitive files + desc: > + Detect symlinks created over a curated list of sensitive files or subdirectories under /etc/ or + root directories. Can be customized as needed. Refer to further and equivalent guidance within the + rule "Read sensitive file untrusted". condition: > - create_symlink and - (evt.arg.target in (sensitive_file_names) or evt.arg.target in (sensitive_directory_names)) - output: > - Symlinks created over sensitive files (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid target=%evt.arg.target linkpath=%evt.arg.linkpath parent_process=%proc.pname) + create_symlink + and (evt.arg.target in (sensitive_file_names) or evt.arg.target in (sensitive_directory_names)) + output: Symlinks created over sensitive files (target=%evt.arg.target linkpath=%evt.arg.linkpath 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 %container.info) priority: WARNING - tags: [host, container, filesystem, mitre_exfiltration, mitre_credential_access, T1020, T1083, T1212, T1552, T1555] + tags: [maturity_stable, host, container, filesystem, mitre_credential_access, T1555] - rule: Create Hardlink Over Sensitive Files - desc: Detect hardlink created over sensitive files + desc: > + Detect hardlink created over a curated list of sensitive files or subdirectories under /etc/ or + root directories. Can be customized as needed. Refer to further and equivalent guidance within the + rule "Read sensitive file untrusted". condition: > - create_hardlink and - (evt.arg.oldpath in (sensitive_file_names)) - output: > - Hardlinks created over sensitive files (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid target=%evt.arg.oldpath linkpath=%evt.arg.newpath parent_process=%proc.pname) + create_hardlink + and (evt.arg.oldpath in (sensitive_file_names)) + output: Hardlinks created over sensitive files (target=%evt.arg.target linkpath=%evt.arg.linkpath 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 %container.info) priority: WARNING - tags: [host, container, filesystem, mitre_exfiltration, mitre_credential_access, T1020, T1083, T1212, T1552, T1555] - -- list: miner_ports - items: [ - 25, 3333, 3334, 3335, 3336, 3357, 4444, - 5555, 5556, 5588, 5730, 6099, 6666, 7777, - 7778, 8000, 8001, 8008, 8080, 8118, 8333, - 8888, 8899, 9332, 9999, 14433, 14444, - 45560, 45700 - ] - -- list: miner_domains - items: [ - "asia1.ethpool.org","ca.minexmr.com", - "cn.stratum.slushpool.com","de.minexmr.com", - "eth-ar.dwarfpool.com","eth-asia.dwarfpool.com", - "eth-asia1.nanopool.org","eth-au.dwarfpool.com", - "eth-au1.nanopool.org","eth-br.dwarfpool.com", - "eth-cn.dwarfpool.com","eth-cn2.dwarfpool.com", - "eth-eu.dwarfpool.com","eth-eu1.nanopool.org", - "eth-eu2.nanopool.org","eth-hk.dwarfpool.com", - "eth-jp1.nanopool.org","eth-ru.dwarfpool.com", - "eth-ru2.dwarfpool.com","eth-sg.dwarfpool.com", - "eth-us-east1.nanopool.org","eth-us-west1.nanopool.org", - "eth-us.dwarfpool.com","eth-us2.dwarfpool.com", - "eu.stratum.slushpool.com","eu1.ethermine.org", - "eu1.ethpool.org","fr.minexmr.com", - "mine.moneropool.com","mine.xmrpool.net", - "pool.minexmr.com","pool.monero.hashvault.pro", - "pool.supportxmr.com","sg.minexmr.com", - "sg.stratum.slushpool.com","stratum-eth.antpool.com", - "stratum-ltc.antpool.com","stratum-zec.antpool.com", - "stratum.antpool.com","us-east.stratum.slushpool.com", - "us1.ethermine.org","us1.ethpool.org", - "us2.ethermine.org","us2.ethpool.org", - "xmr-asia1.nanopool.org","xmr-au1.nanopool.org", - "xmr-eu1.nanopool.org","xmr-eu2.nanopool.org", - "xmr-jp1.nanopool.org","xmr-us-east1.nanopool.org", - "xmr-us-west1.nanopool.org","xmr.crypto-pool.fr", - "xmr.pool.minergate.com", "rx.unmineable.com", - "ss.antpool.com","dash.antpool.com", - "eth.antpool.com","zec.antpool.com", - "xmc.antpool.com","btm.antpool.com", - "stratum-dash.antpool.com","stratum-xmc.antpool.com", - "stratum-btm.antpool.com" - ] - -- list: https_miner_domains - items: [ - "ca.minexmr.com", - "cn.stratum.slushpool.com", - "de.minexmr.com", - "fr.minexmr.com", - "mine.moneropool.com", - "mine.xmrpool.net", - "pool.minexmr.com", - "sg.minexmr.com", - "stratum-eth.antpool.com", - "stratum-ltc.antpool.com", - "stratum-zec.antpool.com", - "stratum.antpool.com", - "xmr.crypto-pool.fr", - "ss.antpool.com", - "stratum-dash.antpool.com", - "stratum-xmc.antpool.com", - "stratum-btm.antpool.com", - "btm.antpool.com" - ] - -- list: http_miner_domains - items: [ - "ca.minexmr.com", - "de.minexmr.com", - "fr.minexmr.com", - "mine.moneropool.com", - "mine.xmrpool.net", - "pool.minexmr.com", - "sg.minexmr.com", - "xmr.crypto-pool.fr" - ] - -# Add rule based on crypto mining IOCs -- macro: minerpool_https - condition: (fd.sport="443" and fd.sip.name in (https_miner_domains)) - -- macro: minerpool_http - condition: (fd.sport="80" and fd.sip.name in (http_miner_domains)) - -- macro: minerpool_other - condition: (fd.sport in (miner_ports) and fd.sip.name in (miner_domains)) - -- macro: net_miner_pool - condition: (evt.type in (sendto, sendmsg, connect) and evt.dir=< and (fd.net != "127.0.0.0/8" and not fd.snet in (rfc_1918_addresses)) and ((minerpool_http) or (minerpool_https) or (minerpool_other))) - -- macro: trusted_images_query_miner_domain_dns - condition: (container.image.repository in (falco_containers)) - -# The rule is disabled by default. -# Note: falco will send DNS request to resolve miner pool domain which may trigger alerts in your environment. -- rule: Detect outbound connections to common miner pool ports - desc: Miners typically connect to miner pools on common ports. - condition: net_miner_pool and not trusted_images_query_miner_domain_dns - enabled: false - output: Outbound connection to IP/Port flagged by https://cryptoioc.ch (command=%proc.cmdline pid=%proc.pid port=%fd.rport ip=%fd.rip container=%container.info image=%container.image.repository) - priority: CRITICAL - tags: [host, container, network, mitre_execution, T1496] - -- rule: Detect crypto miners using the Stratum protocol - desc: Miners typically specify the mining pool to connect to with a URI that begins with 'stratum+tcp' - condition: spawned_process and (proc.cmdline contains "stratum+tcp" or proc.cmdline contains "stratum2+tcp" or proc.cmdline contains "stratum+ssl" or proc.cmdline contains "stratum2+ssl") - output: Possible miner running (command=%proc.cmdline pid=%proc.pid container=%container.info image=%container.image.repository exe_flags=%evt.arg.flags) - priority: CRITICAL - tags: [host, container, process, mitre_execution, T1496] - -- list: k8s_client_binaries - items: [docker, kubectl, crictl] - -# TODO: Remove k8s.gcr.io reference after 01/Dec/2023 -- list: user_known_k8s_ns_kube_system_images - items: [ - k8s.gcr.io/fluentd-gcp-scaler, - k8s.gcr.io/node-problem-detector/node-problem-detector, - registry.k8s.io/fluentd-gcp-scaler, - registry.k8s.io/node-problem-detector/node-problem-detector - ] - -- list: user_known_k8s_images - items: [ - mcr.microsoft.com/aks/hcp/hcp-tunnel-front - ] - -# Whitelist for known docker client binaries run inside container -# - k8s.gcr.io/fluentd-gcp-scaler / registry.k8s.io/fluentd-gcp-scaler in GCP/GKE -# TODO: Remove k8s.gcr.io reference after 01/Dec/2023 -- macro: user_known_k8s_client_container - condition: > - (k8s.ns.name="kube-system" and container.image.repository in (user_known_k8s_ns_kube_system_images)) or container.image.repository in (user_known_k8s_images) - -- macro: user_known_k8s_client_container_parens - condition: (user_known_k8s_client_container) - -- rule: The docker client is executed in a container - desc: Detect a k8s client tool executed inside a container - condition: spawned_process and container and not user_known_k8s_client_container_parens and proc.name in (k8s_client_binaries) - output: "Docker or kubernetes client executed in container (user=%user.name user_loginuid=%user.loginuid %container.info parent=%proc.pname cmdline=%proc.cmdline pid=%proc.pid image=%container.image.repository:%container.image.tag)" - priority: WARNING - tags: [container, mitre_execution, T1610] + tags: [maturity_stable, host, container, filesystem, mitre_credential_access, T1555] - list: user_known_packet_socket_binaries items: [] - rule: Packet socket created in container - desc: Detect new packet socket at the device driver (OSI Layer 2) level in a container. Packet socket could be used for ARP Spoofing and privilege escalation(CVE-2020-14386) by attacker. - condition: evt.type=socket and evt.arg[0] contains AF_PACKET and container and not proc.name in (user_known_packet_socket_binaries) - output: Packet socket was created in a container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid socket_info=%evt.args container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag) + desc: > + Detect new packet socket at the device driver (OSI Layer 2) level in a container. Packet socket could be used for ARP Spoofing + and privilege escalation (CVE-2020-14386) by an attacker. Noise can be reduced by using the user_known_packet_socket_binaries + template list. + condition: > + evt.type=socket + and container + and evt.arg[0] contains AF_PACKET + and not proc.name in (user_known_packet_socket_binaries) + output: Packet socket was created in a container (socket_info=%evt.args connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto 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 %container.info) priority: NOTICE - tags: [container, network, mitre_discovery, T1046] - -# Namespaces where the rule is enforce -- list: namespace_scope_network_only_subnet - items: [] - -- macro: network_local_subnet - condition: > - fd.rnet in (rfc_1918_addresses) or - fd.ip = "0.0.0.0" or - fd.net = "127.0.0.0/8" - -# # The rule is disabled by default. -# # How to test: -# # Add 'default' to namespace_scope_network_only_subnet -# # Run: -# kubectl run --generator=run-pod/v1 -n default -i --tty busybox --image=busybox --rm -- wget google.com -O /var/google.html -# # Check logs running - -- rule: Network Connection outside Local Subnet - desc: Detect traffic to image outside local subnet. - condition: > - inbound_outbound and - container and - not network_local_subnet and - k8s.ns.name in (namespace_scope_network_only_subnet) - enabled: false - output: > - Network connection outside local subnet - (command=%proc.cmdline pid=%proc.pid connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id - image=%container.image.repository namespace=%k8s.ns.name - fd.rip.name=%fd.rip.name fd.lip.name=%fd.lip.name fd.cip.name=%fd.cip.name fd.sip.name=%fd.sip.name) - priority: WARNING - tags: [container, network, mitre_discovery, T1046] - -- list: allowed_image - items: [] # add image to monitor, i.e.: bitnami/nginx - -- list: authorized_server_binary - items: [] # add binary to allow, i.e.: nginx - -- list: authorized_server_port - items: [] # add port to allow, i.e.: 80 - -# # How to test: -# kubectl run --image=nginx nginx-app --port=80 --env="DOMAIN=cluster" -# kubectl expose deployment nginx-app --port=80 --name=nginx-http --type=LoadBalancer -# # On minikube: -# minikube service nginx-http -# # On general K8s: -# kubectl get services -# kubectl cluster-info -# # Visit the Nginx service and port, should not fire. -# # Change rule to different port, then different process name, and test again that it fires. - -- rule: Outbound or Inbound Traffic not to Authorized Server Process and Port - desc: Detect traffic that is not to authorized server process and port. - condition: > - inbound_outbound and - container and - container.image.repository in (allowed_image) and - not proc.name in (authorized_server_binary) and - not fd.sport in (authorized_server_port) - enabled: false - output: > - Network connection outside authorized port and binary - (command=%proc.cmdline pid=%proc.pid connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id - image=%container.image.repository) - priority: WARNING - tags: [container, network, mitre_discovery, TA0011] + tags: [maturity_stable, container, network, mitre_credential_access, T1557.002] - macro: user_known_stand_streams_redirect_activities condition: (never_true) -- macro: dup - condition: evt.type in (dup, dup2, dup3) - -- rule: Redirect STDOUT/STDIN to Network Connection in Container - desc: Detect redirecting stdout/stdin to network connection in container (potential reverse shell). - condition: dup and container and evt.rawres in (0, 1, 2) and fd.type in ("ipv4", "ipv6") and not user_known_stand_streams_redirect_activities - output: > - Redirect stdout/stdin to network connection (user=%user.name user_loginuid=%user.loginuid %container.info process=%proc.name parent=%proc.pname cmdline=%proc.cmdline pid=%proc.pid terminal=%proc.tty container_id=%container.id image=%container.image.repository fd.name=%fd.name fd.num=%fd.num fd.type=%fd.type fd.sip=%fd.sip) - priority: NOTICE - tags: [container, network, process, mitre_discovery, mitre_execution, T1059] - -# The two Container Drift rules below will fire when a new executable is created in a container. -# There are two ways to create executables - file is created with execution permissions or permissions change of existing file. -# We will use a new filter, is_open_exec, to find all files creations with execution permission, and will trace all chmods in a container. -# The use case we are targeting here is an attempt to execute code that was not shipped as part of a container (drift) - -# an activity that might be malicious or non-compliant. -# Two things to pay attention to: -# 1) In most cases, 'docker cp' will not be identified, but the assumption is that if an attacker gained access to the container runtime daemon, they are already privileged -# 2) Drift rules will be noisy in environments in which containers are built (e.g. docker build) -# These two rules are not enabled by default. - -- macro: user_known_container_drift_activities - condition: (always_true) - -- rule: Container Drift Detected (chmod) - desc: New executable created in a container due to chmod - condition: > - chmod and - container and - not runc_writing_exec_fifo and - not runc_writing_var_lib_docker and - not user_known_container_drift_activities and - evt.rawres>=0 and - ((evt.arg.mode contains "S_IXUSR") or - (evt.arg.mode contains "S_IXGRP") or - (evt.arg.mode contains "S_IXOTH")) - enabled: false - output: Drift detected (chmod), new executable created in a container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode event=%evt.type) - priority: ERROR - tags: [container, process, filesystem, mitre_execution, T1059] - -# **************************************************************************** -# * "Container Drift Detected (open+create)" requires FALCO_ENGINE_VERSION 6 * -# **************************************************************************** -- rule: Container Drift Detected (open+create) - desc: New executable created in a container due to open+create - condition: > - evt.type in (open,openat,openat2,creat) and - evt.is_open_exec=true and - container and - not runc_writing_exec_fifo and - not runc_writing_var_lib_docker and - not user_known_container_drift_activities and - evt.rawres>=0 - enabled: false - output: Drift detected (open+create), new executable created in a container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode event=%evt.type) - priority: ERROR - tags: [container, process, filesystem, mitre_execution, T1059] - -- list: c2_server_ip_list - items: [] - -- list: c2_server_fqdn_list - items: [] - -# For example, you can fetch a list of IP addresses and FQDN on this website: -# https://feodotracker.abuse.ch/downloads/ipblocklist_recommended.json. -# Use Falco HELM chart to update (append) the c2 server lists with your values. -# See an example below. +# As of engine version 20 this rule can be improved by using the fd.types[] +# field so it only triggers once when all three of std{out,err,in} are +# redirected. # -# ```yaml -# # values.yaml Falco HELM chart file -# [...] -# customRules: -# c2-servers-list.yaml: |- -# - list: c2_server_ip_list -# append: true -# items: -# - "'51.178.161.32'" -# - "'46.101.90.205'" -# -# - list: c2_server_fqdn_list -# append: true -# items: -# - "srv-web.ffconsulting.com" -# - "57.ip-142-44-247.net" -# ``` - -- rule: Outbound Connection to C2 Servers - desc: Detect outbound connection to command & control servers thanks to a list of IP addresses & a list of FQDN. - condition: > - outbound and - ((fd.sip in (c2_server_ip_list)) or - (fd.sip.name in (c2_server_fqdn_list))) - output: Outbound connection to C2 server (c2_domain=%fd.sip.name c2_addr=%fd.sip command=%proc.cmdline connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository) - priority: WARNING - enabled: false - tags: [host, container, network, mitre_command_and_control, TA0011] +# - list: ip_sockets +# items: ["ipv4", "ipv6"] +# +# - rule: Redirect STDOUT/STDIN to Network Connection in Container once +# condition: dup and container and evt.rawres in (0, 1, 2) and fd.type in (ip_sockets) and fd.types[0] in (ip_sockets) and fd.types[1] in (ip_sockets) and fd.types[2] in (ip_sockets) and not user_known_stand_streams_redirect_activities +# +# The following rule has not been changed by default as existing users could be +# relying on the rule triggering when any of std{out,err,in} are redirected. +- rule: Redirect STDOUT/STDIN to Network Connection in Container + desc: > + Detect redirection of stdout/stdin to a network connection within a container, achieved by utilizing a + variant of the dup syscall (potential reverse shell or remote code execution + https://github.com/swisskyrepo/PayloadsAllTheThings/). This detection is behavior-based and may generate + noise in the system, and can be adjusted using the user_known_stand_streams_redirect_activities template + macro. Tuning can be performed similarly to existing detections based on process lineage or container images, + and/or it can be limited to interactive tty (tty != 0). + condition: > + dup + and container + and evt.rawres in (0, 1, 2) + and fd.type in ("ipv4", "ipv6") + and not user_known_stand_streams_redirect_activities + output: Redirect stdout/stdin to network connection (gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] fd.sip=%fd.sip connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto 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 %container.info) + priority: NOTICE + tags: [maturity_stable, container, network, process, mitre_execution, T1059] - list: allowed_container_images_loading_kernel_module items: [] -# init_module and finit_module syscalls are available since Falco 0.35.0 -# rule coverage now extends to modprobe usage via init_module logging -# and previous alerting on spawned_process and insmod is now covered -# by finit_module syscall - rule: Linux Kernel Module Injection Detected - desc: Detect kernel module was injected (from container). - condition: kernel_module_load and container + desc: > + Inject Linux Kernel Modules from containers using insmod or modprobe with init_module and finit_module + syscalls, given the precondition of sys_module effective capabilities. Profile the environment and consider + allowed_container_images_loading_kernel_module to reduce noise and account for legitimate cases. + condition: > + kernel_module_load + and container + and thread.cap_effective icontains sys_module and not container.image.repository in (allowed_container_images_loading_kernel_module) - and thread.cap_effective icontains sys_module - output: Linux Kernel Module injection from container detected (user=%user.name uid=%user.uid user_loginuid=%user.loginuid process_name=%proc.name parent_process_name=%proc.pname parent_exepath=%proc.pexepath %proc.aname[2] %proc.aexepath[2] module=%proc.args %container.info image=%container.image.repository:%container.image.tag res=%evt.res syscall=%evt.type) + output: Linux Kernel Module injection from container (parent_exepath=%proc.pexepath gparent=%proc.aname[2] gexepath=%proc.aexepath[2] module=%proc.args res=%evt.res 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 %container.info) priority: WARNING - tags: [host, container, process, mitre_execution, mitre_persistence, TA0002] - -- list: run_as_root_image_list - items: [] - -- macro: user_known_run_as_root_container - condition: (container.image.repository in (run_as_root_image_list)) - -# The rule is disabled by default and should be enabled when non-root container policy has been applied. -# Note the rule will not work as expected when usernamespace is applied, e.g. userns-remap is enabled. -- rule: Container Run as Root User - desc: Detected container running as root user - condition: spawned_process and container and proc.vpid=1 and user.uid=0 and not user_known_run_as_root_container - enabled: false - output: Container launched with root user privilege (uid=%user.uid container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) - priority: INFO - tags: [container, process, users, mitre_execution, T1610] - -# This rule helps detect CVE-2021-3156: -# A privilege escalation to root through heap-based buffer overflow -- rule: Sudo Potential Privilege Escalation - desc: Privilege escalation vulnerability affecting sudo (<= 1.9.5p2). Executing sudo using sudoedit -s or sudoedit -i command with command-line argument that ends with a single backslash character from an unprivileged user it's possible to elevate the user privileges to root. - condition: spawned_process and user.uid != 0 and (proc.name=sudoedit or proc.name = sudo) and (proc.args contains -s or proc.args contains -i or proc.args contains --login) and (proc.args contains "\ " or proc.args endswith \) - output: "Detect Sudo Privilege Escalation Exploit (CVE-2021-3156) (user=%user.name parent=%proc.pname cmdline=%proc.cmdline pid=%proc.pid exe_flags=%evt.arg.flags %container.info)" - priority: CRITICAL - tags: [host, container, filesystem, users, mitre_privilege_escalation, T1548.003] + tags: [maturity_stable, host, container, process, mitre_persistence, TA0003] - rule: Debugfs Launched in Privileged Container - desc: Detect file system debugger debugfs launched inside a privileged container which might lead to container escape. + desc: > + Detect file system debugger debugfs launched inside a privileged container which might lead to container escape. + This rule has a more narrow scope. condition: > - spawned_process and container + spawned_process + and container and container.privileged=true and proc.name=debugfs - output: Debugfs launched started in a privileged container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) + output: Debugfs launched started in a privileged 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 %container.info) priority: WARNING - tags: [container, cis, process, mitre_execution, mitre_lateral_movement, T1611] - -- macro: mount_info - condition: (proc.args="" or proc.args intersects ("-V", "-l", "-h")) - -- macro: known_gke_mount_in_privileged_containers - condition: - (k8s.ns.name = kube-system - and container.image.repository = gke.gcr.io/gcp-compute-persistent-disk-csi-driver) - -- macro: known_aks_mount_in_privileged_containers - condition: - ((k8s.ns.name = kube-system and container.image.repository in (mcr.microsoft.com/oss/kubernetes-csi/azuredisk-csi,mcr.microsoft.com/oss/kubernetes-csi/azurefile-csi)) - or (k8s.ns.name = system and container.image.repository = mcr.microsoft.com/oss/kubernetes-csi/secrets-store/driver)) - -- macro: user_known_mount_in_privileged_containers - condition: (never_true) - -- rule: Mount Launched in Privileged Container - desc: Detect file system mount happened inside a privileged container which might lead to container escape. - condition: > - spawned_process and container - and container.privileged=true - and proc.name=mount - and not mount_info - and not known_gke_mount_in_privileged_containers - and not known_aks_mount_in_privileged_containers - and not user_known_mount_in_privileged_containers - output: Mount was executed inside a privileged container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) - priority: WARNING - tags: [container, cis, filesystem, mitre_lateral_movement, T1611] - -- list: user_known_userfaultfd_processes - items: [] - -- rule: Unprivileged Delegation of Page Faults Handling to a Userspace Process - desc: Detect a successful unprivileged userfaultfd syscall which might act as an attack primitive to exploit other bugs - condition: > - evt.type = userfaultfd and - user.uid != 0 and - (evt.rawres >= 0 or evt.res != -1) and - not proc.name in (user_known_userfaultfd_processes) - output: An userfaultfd syscall was successfully executed by an unprivileged user (user=%user.name user_loginuid=%user.loginuid process=%proc.name command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag) - priority: CRITICAL - tags: [host, container, process, mitre_defense_evasion, TA0005] - -- list: ingress_remote_file_copy_binaries - items: [wget] - -- macro: ingress_remote_file_copy_procs - condition: (proc.name in (ingress_remote_file_copy_binaries)) - -# Users should overwrite this macro to specify conditions under which a -# Custom condition for use of ingress remote file copy tool in container -- macro: user_known_ingress_remote_file_copy_activities - condition: (never_true) - -- macro: curl_download - condition: proc.name = curl and - (proc.cmdline contains " -o " or - proc.cmdline contains " --output " or - proc.cmdline contains " -O " or - proc.cmdline contains " --remote-name ") - -- rule: Launch Ingress Remote File Copy Tools in Container - desc: Detect ingress remote file copy tools launched in container - condition: > - spawned_process and - container and - (ingress_remote_file_copy_procs or curl_download) and - not user_known_ingress_remote_file_copy_activities - output: > - Ingress remote file copy tool launched in container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid parent_process=%proc.pname - container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) - priority: NOTICE - tags: [container, network, process, mitre_command_and_control, TA0011] - -# This rule helps detect CVE-2021-4034: -# A privilege escalation to root through memory corruption -- rule: Polkit Local Privilege Escalation Vulnerability (CVE-2021-4034) - desc: "This rule detects an attempt to exploit a privilege escalation vulnerability in Polkit's pkexec. By running specially crafted code, a local user can leverage this flaw to gain root privileges on a compromised system" - condition: - spawned_process and user.uid != 0 and proc.name=pkexec and proc.args = '' - output: - "Detect Polkit pkexec Local Privilege Escalation Exploit (CVE-2021-4034) (user=%user.loginname uid=%user.loginuid command=%proc.cmdline pid=%proc.pid args=%proc.args exe_flags=%evt.arg.flags)" - priority: CRITICAL - tags: [host, container, process, users, mitre_privilege_escalation, TA0004] - + tags: [maturity_stable, container, cis, process, mitre_privilege_escalation, T1611] - rule: Detect release_agent File Container Escapes - desc: "This rule detect an attempt to exploit a container escape using release_agent file. By running a container with certains capabilities, a privileged user can modify release_agent file and escape from the container" - condition: - open_write and container and fd.name endswith release_agent and (user.uid=0 or thread.cap_effective contains CAP_DAC_OVERRIDE) and thread.cap_effective contains CAP_SYS_ADMIN - output: - "Detect an attempt to exploit a container escape using release_agent file (user=%user.name user_loginuid=%user.loginuid filename=%fd.name %container.info image=%container.image.repository:%container.image.tag cap_effective=%thread.cap_effective)" - priority: CRITICAL - tags: [container, process, mitre_privilege_escalation, mitre_lateral_movement, T1611] - -# Rule for detecting potential Log4Shell (CVE-2021-44228) exploitation -# Note: Not compatible with Java 17+, which uses read() syscalls -- macro: java_network_read - condition: (evt.type=recvfrom and fd.type in (ipv4, ipv6) and proc.name=java) - -- rule: Java Process Class File Download - desc: Detected Java process downloading a class file which could indicate a successful exploit of the log4shell Log4j vulnerability (CVE-2021-44228) + desc: > + Detect an attempt to exploit a container escape using release_agent file. + By running a container with certains capabilities, a privileged user can modify + release_agent file and escape from the container. condition: > - java_network_read and evt.buffer bcontains cafebabe - output: Java process class file download (user=%user.name user_loginname=%user.loginname user_loginuid=%user.loginuid event=%evt.type connection=%fd.name server_ip=%fd.sip server_port=%fd.sport proto=%fd.l4proto process=%proc.name command=%proc.cmdline pid=%proc.pid parent=%proc.pname buffer=%evt.buffer container_id=%container.id image=%container.image.repository) + open_write + and container + and fd.name endswith release_agent + and (user.uid=0 or thread.cap_effective contains CAP_DAC_OVERRIDE) + and thread.cap_effective contains CAP_SYS_ADMIN + output: Detect an attempt to exploit a container escape using release_agent file (file=%fd.name cap_effective=%thread.cap_effective 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 %container.info) priority: CRITICAL - enabled: false - tags: [host, container, process, mitre_initial_access, T1190] + tags: [maturity_stable, container, process, mitre_privilege_escalation, T1611] - list: docker_binaries items: [docker, dockerd, containerd-shim, "runc:[1:CHILD]", pause, exe, docker-compose, docker-entrypoi, docker-runc-cur, docker-current, dockerd-current] -- macro: docker_procs - condition: proc.name in (docker_binaries) - -- rule: Modify Container Entrypoint - desc: This rule detect an attempt to write on container entrypoint symlink (/proc/self/exe). Possible CVE-2019-5736 Container Breakout exploitation attempt. - condition: > - open_write and container and (fd.name=/proc/self/exe or fd.name startswith /proc/self/fd/) and not docker_procs and not proc.cmdline = "runc:[1:CHILD] init" - enabled: false - output: > - Detect Potential Container Breakout Exploit (CVE-2019-5736) (user=%user.name process=%proc.name file=%fd.name cmdline=%proc.cmdline pid=%proc.pid %container.info) - priority: WARNING - tags: [container, filesystem, mitre_initial_access, T1611] - -- list: known_binaries_to_read_environment_variables_from_proc_files - items: [scsi_id, argoexec] - -- rule: Read environment variable from /proc files - desc: An attempt to read process environment variables from /proc files - condition: > - open_read and container and (fd.name glob /proc/*/environ) - and not proc.name in (known_binaries_to_read_environment_variables_from_proc_files) - output: > - Environment variables were retrieved from /proc files (user=%user.name user_loginuid=%user.loginuid program=%proc.name - command=%proc.cmdline pid=%proc.pid file=%fd.name parent=%proc.pname gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] container_id=%container.id image=%container.image.repository) - priority: WARNING - tags: [container, filesystem, process, mitre_credential_access, mitre_discovery, T1083] - - list: known_ptrace_binaries items: [] @@ -3337,29 +1095,39 @@ - macro: ptrace_attach_or_injection condition: > - evt.type=ptrace and evt.dir=> and + (evt.type=ptrace and evt.dir=> and (evt.arg.request contains PTRACE_POKETEXT or evt.arg.request contains PTRACE_POKEDATA or evt.arg.request contains PTRACE_ATTACH or evt.arg.request contains PTRACE_SEIZE or - evt.arg.request contains PTRACE_SETREGS) + evt.arg.request contains PTRACE_SETREGS)) - rule: PTRACE attached to process - desc: "This rule detects an attempt to inject code into a process using PTRACE." - condition: ptrace_attach_or_injection and proc_name_exists and not known_ptrace_procs - output: > - Detected ptrace PTRACE_ATTACH attempt (proc.cmdline=%proc.cmdline container=%container.info evt.type=%evt.type evt.arg.request=%evt.arg.request proc.pid=%proc.pid proc.cwd=%proc.cwd proc.ppid=%proc.ppid - proc.pcmdline=%proc.pcmdline proc.sid=%proc.sid proc.exepath=%proc.exepath user.uid=%user.uid user.loginuid=%user.loginuid user.loginname=%user.loginname user.name=%user.name group.gid=%group.gid - group.name=%group.name container.id=%container.id container.name=%container.name image=%container.image.repository) + desc: > + Detect an attempt to inject potentially malicious code into a process using PTRACE in order to evade + process-based defenses or elevate privileges. Common anti-patterns are debuggers. Additionally, profiling + your environment via the known_ptrace_procs template macro can reduce noise. + A successful ptrace syscall generates multiple logs at once. + condition: > + ptrace_attach_or_injection + and proc_name_exists + and not known_ptrace_procs + output: Detected ptrace PTRACE_ATTACH attempt (proc_pcmdline=%proc.pcmdline 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 %container.info) priority: WARNING - tags: [host, container, process, mitre_execution, mitre_privilege_escalation, T1055.008] + tags: [maturity_stable, host, container, process, mitre_privilege_escalation, T1055.008] - rule: PTRACE anti-debug attempt - desc: "Detect usage of the PTRACE system call with the PTRACE_TRACEME argument, indicating a program actively attempting to avoid debuggers attaching to the process. This behavior is typically indicative of malware activity." - condition: evt.type=ptrace and evt.dir=> and evt.arg.request contains PTRACE_TRACEME and proc_name_exists - output: Detected potential PTRACE_TRACEME anti-debug attempt (proc.cmdline=%proc.cmdline container=%container.info evt.type=%evt.type evt.arg.request=%evt.arg.request proc.pid=%proc.pid proc.cwd=%proc.cwd proc.ppid=%proc.ppid proc.pcmdline=%proc.pcmdline proc.sid=%proc.sid proc.exepath=%proc.exepath user.uid=%user.uid user.loginuid=%user.loginuid user.loginname=%user.loginname user.name=%user.name group.gid=%group.gid group.name=%group.name container.id=%container.id container.name=%container.name image=%container.image.repository) + desc: > + Detect usage of the PTRACE system call with the PTRACE_TRACEME argument, indicating a program actively attempting + to avoid debuggers attaching to the process. This behavior is typically indicative of malware activity. + Read more about PTRACE in the "PTRACE attached to process" rule. + condition: > + evt.type=ptrace and evt.dir=> + and evt.arg.request contains PTRACE_TRACEME + and proc_name_exists + output: Detected potential PTRACE_TRACEME anti-debug attempt (proc_pcmdline=%proc.pcmdline 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 %container.info) priority: NOTICE - tags: [host, container, process, mitre_defense_evasion, T1622] + tags: [maturity_stable, host, container, process, mitre_defense_evasion, T1622] - macro: private_aws_credentials condition: > @@ -3370,54 +1138,114 @@ proc.args icontains "secretaccesskey") - rule: Find AWS Credentials - desc: Find or grep AWS credentials + desc: > + Detect attempts to search for private keys or passwords using the grep or find command, particularly targeting standard + AWS credential locations. This is often seen with unsophisticated attackers, as there are many ways to access files + using bash built-ins that could go unnoticed. Regardless, this serves as a solid baseline detection that can be tailored + to cover these gaps while maintaining an acceptable noise level. This rule complements the rule "Search Private Keys or Passwords". condition: > - spawned_process and - ((grep_commands and private_aws_credentials) or - (proc.name = "find" and proc.args endswith ".aws/credentials")) - output: Detected AWS credentials search activity (user.name=%user.name user.loginuid=%user.loginuid proc.cmdline=%proc.cmdline container.id=%container.id container_name=%container.name evt.type=%evt.type evt.res=%evt.res proc.pid=%proc.pid proc.cwd=%proc.cwd proc.ppid=%proc.ppid proc.pcmdline=%proc.pcmdline proc.sid=%proc.sid proc.exepath=%proc.exepath user.uid=%user.uid user.loginname=%user.loginname group.gid=%group.gid group.name=%group.name container.name=%container.name image=%container.image.repository:%container.image.tag exe_flags=%evt.arg.flags) + spawned_process + and ((grep_commands and private_aws_credentials) or + (proc.name = "find" and proc.args endswith ".aws/credentials")) + output: Detected AWS credentials search activity (proc_pcmdline=%proc.pcmdline proc_cwd=%proc.cwd group_gid=%group.gid group_name=%group.name user_loginname=%user.loginname 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 %container.info) priority: WARNING - tags: [host, container, mitre_credential_access, process, aws, T1552] + tags: [maturity_stable, host, container, process, aws, mitre_credential_access, T1552] - rule: Execution from /dev/shm - desc: This rule detects file execution from the /dev/shm directory, a common tactic for threat actors to stash their readable+writable+(sometimes)executable files. + desc: > + This rule detects file execution in the /dev/shm directory, a tactic often used by threat actors to store their readable, writable, and + occasionally executable files. /dev/shm acts as a link to the host or other containers, creating vulnerabilities for their compromise + as well. Notably, /dev/shm remains unchanged even after a container restart. Consider this rule alongside the newer + "Drop and execute new binary in container" rule. condition: > - spawned_process and - (proc.exe startswith "/dev/shm/" or - (proc.cwd startswith "/dev/shm/" and proc.exe startswith "./" ) or - (shell_procs and proc.args startswith "-c /dev/shm") or - (shell_procs and proc.args startswith "-i /dev/shm") or - (shell_procs and proc.args startswith "/dev/shm") or - (proc.cwd startswith "/dev/shm/" and proc.args startswith "./" )) and - not container.image.repository in (falco_privileged_images, trusted_images) - output: "File execution detected from /dev/shm (proc.cmdline=%proc.cmdline connection=%fd.name user.name=%user.name user.loginuid=%user.loginuid container.id=%container.id evt.type=%evt.type evt.res=%evt.res proc.pid=%proc.pid proc.cwd=%proc.cwd proc.ppid=%proc.ppid proc.pcmdline=%proc.pcmdline proc.sid=%proc.sid proc.exepath=%proc.exepath user.uid=%user.uid user.loginname=%user.loginname group.gid=%group.gid group.name=%group.name container.name=%container.name image=%container.image.repository exe_flags=%evt.arg.flags)" + spawned_process + and (proc.exe startswith "/dev/shm/" or + (proc.cwd startswith "/dev/shm/" and proc.exe startswith "./" ) or + (shell_procs and proc.args startswith "-c /dev/shm") or + (shell_procs and proc.args startswith "-i /dev/shm") or + (shell_procs and proc.args startswith "/dev/shm") or + (proc.cwd startswith "/dev/shm/" and proc.args startswith "./" )) + and not container.image.repository in (falco_privileged_images, trusted_images) + output: File execution detected from /dev/shm (evt_res=%evt.res file=%fd.name proc_cwd=%proc.cwd proc_pcmdline=%proc.pcmdline user_loginname=%user.loginname group_gid=%group.gid group_name=%group.name 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 %container.info) priority: WARNING - tags: [host, container, mitre_execution, mitre_defense_evasion, T1036.005, T1059.004] - + tags: [maturity_stable, host, container, mitre_execution, T1059.004] + # List of allowed container images that are known to execute binaries not part of their base image. -# Users can use this list to better tune the rule below (i.e reducing false positives) by considering their workloads, -# since this requires application specific knowledge. - list: known_drop_and_execute_containers items: [] - rule: Drop and execute new binary in container - desc: + desc: > Detect if an executable not belonging to the base image of a container is being executed. The drop and execute pattern can be observed very often after an attacker gained an initial foothold. is_exe_upper_layer filter field only applies for container runtimes that use overlayfs as union mount filesystem. + Adopters can utilize the provided template list known_drop_and_execute_containers containing allowed container + images known to execute binaries not included in their base image. Alternatively, you could exclude non-production + namespaces in Kubernetes settings by adjusting the rule further. This helps reduce noise by applying application + and environment-specific knowledge to this rule. Common anti-patterns include administrators or SREs performing + ad-hoc debugging. condition: > spawned_process and container and proc.is_exe_upper_layer=true and not container.image.repository in (known_drop_and_execute_containers) - output: > - Executing binary not part of base image (user=%user.name user_loginuid=%user.loginuid user_uid=%user.uid comm=%proc.cmdline exe=%proc.exe container_id=%container.id - image=%container.image.repository proc.name=%proc.name proc.sname=%proc.sname proc.pname=%proc.pname proc.aname[2]=%proc.aname[2] exe_flags=%evt.arg.flags - proc.exe_ino=%proc.exe_ino proc.exe_ino.ctime=%proc.exe_ino.ctime proc.exe_ino.mtime=%proc.exe_ino.mtime proc.exe_ino.ctime_duration_proc_start=%proc.exe_ino.ctime_duration_proc_start - proc.exepath=%proc.exepath proc.cwd=%proc.cwd proc.tty=%proc.tty container.start_ts=%container.start_ts proc.sid=%proc.sid proc.vpgid=%proc.vpgid evt.res=%evt.res) - priority: CRITICAL - tags: [container, mitre_persistence, TA0003] + output: Executing binary not part of base image (proc_exe=%proc.exe proc_sname=%proc.sname gparent=%proc.aname[2] proc_exe_ino_ctime=%proc.exe_ino.ctime proc_exe_ino_mtime=%proc.exe_ino.mtime proc_exe_ino_ctime_duration_proc_start=%proc.exe_ino.ctime_duration_proc_start proc_cwd=%proc.cwd container_start_ts=%container.start_ts 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 %container.info) + priority: CRITICAL + tags: [maturity_stable, container, process, mitre_persistence, TA0003, PCI_DSS_11.5.1] -# Application rules have moved to application_rules.yaml. Please look -# there if you want to enable them by adding to -# falco_rules.local.yaml. +# RFC1918 addresses were assigned for private network usage +- list: rfc_1918_addresses + items: ['"10.0.0.0/8"', '"172.16.0.0/12"', '"192.168.0.0/16"'] + +- macro: outbound + condition: > + (((evt.type = connect and evt.dir=<) or + (evt.type in (sendto,sendmsg) and evt.dir=< and + fd.l4proto != tcp and fd.connected=false and fd.name_changed=true)) and + (fd.typechar = 4 or fd.typechar = 6) and + (fd.ip != "0.0.0.0" and fd.net != "127.0.0.0/8" and not fd.snet in (rfc_1918_addresses)) and + (evt.rawres >= 0 or evt.res = EINPROGRESS)) + +- list: ssh_non_standard_ports + items: [80, 8080, 88, 443, 8443, 53, 4444] + +- macro: ssh_non_standard_ports_network + condition: (fd.sport in (ssh_non_standard_ports)) + +- rule: Disallowed SSH Connection Non Standard Port + desc: > + Detect any new outbound SSH connection from the host or container using a non-standard port. This rule holds the potential + to detect a family of reverse shells that cause the victim machine to connect back out over SSH, with STDIN piped from + the SSH connection to a shell's STDIN, and STDOUT of the shell piped back over SSH. Such an attack can be launched against + any app that is vulnerable to command injection. The upstream rule only covers a limited selection of non-standard ports. + We suggest adding more ports, potentially incorporating ranges based on your environment's knowledge and custom SSH port + configurations. This rule can complement the "Redirect STDOUT/STDIN to Network Connection in Container" or + "Disallowed SSH Connection" rule. + condition: > + outbound + and proc.exe endswith ssh + and fd.l4proto=tcp + and ssh_non_standard_ports_network + output: Disallowed SSH Connection (connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto 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 %container.info) + priority: NOTICE + tags: [maturity_stable, host, container, network, process, mitre_execution, T1059] + +- list: known_memfd_execution_binaries + items: [] + +- macro: known_memfd_execution_processes + condition: (proc.name in (known_memfd_execution_binaries)) + +- rule: Fileless execution via memfd_create + desc: > + Detect if a binary is executed from memory using the memfd_create technique. This is a well-known defense evasion + technique for executing malware on a victim machine without storing the payload on disk and to avoid leaving traces + about what has been executed. Adopters can whitelist processes that may use fileless execution for benign purposes + by adding items to the list known_memfd_execution_processes. + condition: > + spawned_process + and proc.is_exe_from_memfd=true + and not known_memfd_execution_processes + output: Fileless execution via memfd_create (container_start_ts=%container.start_ts proc_cwd=%proc.cwd evt_res=%evt.res proc_sname=%proc.sname gparent=%proc.aname[2] 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 %container.info) + priority: CRITICAL + tags: [maturity_stable, host, container, process, mitre_defense_evasion, T1620]