mirror of
https://github.com/falcosecurity/falco.git
synced 2025-06-29 08:07:24 +00:00
Another round of rule cleanups.
Do another round of rule cleanups now that we have a larger set of positive and negative trace files to work with. Outside of this commit, there are now trace files for all the positive rules, a docker-compose startup and teardown, and some trace files from the sysdig cloud staging environment. Also add a script that runs sysdig with a filter that removes all the syscalls not handled by falco as well as a few other high-volume, low-information syscalls. This script was used to create the staging environment trace files. Notable rule changes: - The direction for write_binary_dir/write_etc needs to be exit instead of enter, as the bin_dir clause works on the file descriptor returned by the open/openat call. - Add login as a trusted binary that can read sensitive files (occurs for direct console logins). - sshd can read sensitive files well after startup, so exclude it from the set of binaries that can trigger read_sensitive_file_trusted_after_startup. - limit run_shell_untrusted to non-containers. - Disable the ssh_error_syslog rule for now. With the current restriction on system calls (no read/write/sendto/recvfrom/etc), you won't see the ssh error messages. Nevertheless, add a string to look for to indicate ssh errors and add systemd's true location for the syslog device. - Sshd attemps to setuid even when it's not running as root, so exclude it from the set of binaries to monitor for now. - Let programs that are direct decendants of systemd spawn user management tasks for now. - Temporarily disable the EACCESS rule. This rule is exposing a bug in sysdig in debug mode, https://github.com/draios/sysdig/issues/598. The rule is also pretty noisy so I'll keep it disabled until the sysdig bug is fixed. - The etc_dir and bin_dir macros both have the problem that they match pathnames with /etc/, /bin/, etc in the middle of the path, as sysdig doesn't have a "begins with" comparison. Add notes for that. - Change spawn_process to spawned_process to indicate that it's for the exit side of the execve. Also use it in a few places that were looking for the same conditions without any macro. - Get rid of adduser_binaries and fold any programs not already present into shadowutils_binaries. - Add new groups sysdigcloud_binaries and sysdigcloud_binaries_parent and add them as exceptions for write_etc/write_binary_dir. - Add yum as a package management binary and add it as an exception to write_etc/write_binary_dir. - Change how db_program_spawned_process works. Since all of the useful information is on the exit side of the event, you can't really add a condition based on the process being new. Isntead, have the rule check for a non-database-related program being spawned by a database-related program. - Allow dragent to run shells. - Add sendmail, sendmail-msp as a program that attempts to setuid. - Some of the *_binaries macros that were based on dpkg -L accidentally contained directories in addition to end files. Trim those. - Add systemd-logind as a login_binary. - Add unix_chkpwd as a shadowutils_binary. - Add parentheses around any macros that group items using or. I found this necessary when the macro is used in the middle of a list of and conditions. - Break out system_binaries into a new subset user_mgmt_binaries containing login_, passwd_, and shadowutils_ binaries. That way you don't have to pull in all of system_binaries when looking for sensisitive files or user management activity. - Rename fs-bash to fbash, thinking ahead to its more likely name.
This commit is contained in:
parent
4751546c03
commit
b3ae480fac
@ -38,12 +38,16 @@
|
||||
- macro: modify
|
||||
condition: rename or remove
|
||||
|
||||
- macro: spawn_process
|
||||
condition: syscall.type = execve and evt.dir=<
|
||||
- macro: spawned_process
|
||||
condition: evt.type = execve and evt.dir=<
|
||||
|
||||
# File categories
|
||||
- macro: terminal_file_fd
|
||||
condition: fd.name=/dev/ptmx or fd.directory=/dev/pts
|
||||
|
||||
# This really should be testing that the directory begins with these
|
||||
# prefixes but sysdig's filter doesn't have a "starts with" operator
|
||||
# (yet).
|
||||
- macro: bin_dir
|
||||
condition: fd.directory in (/bin, /sbin, /usr/bin, /usr/sbin)
|
||||
|
||||
@ -52,6 +56,8 @@
|
||||
- macro: bin_dir_rename
|
||||
condition: evt.arg[1] contains /bin/ or evt.arg[1] contains /sbin/ or evt.arg[1] contains /usr/bin/ or evt.arg[1] contains /usr/sbin/
|
||||
|
||||
# This really should be testing that the directory begins with /etc,
|
||||
# but sysdig's filter doesn't have a "starts with" operator (yet).
|
||||
- macro: etc_dir
|
||||
condition: fd.directory contains /etc
|
||||
|
||||
@ -74,25 +80,31 @@
|
||||
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)
|
||||
- macro: adduser_binaries
|
||||
condition: proc.name in (adduser, deluser, addgroup, delgroup)
|
||||
- macro: login_binaries
|
||||
condition: proc.name in (bin, login, su, sbin, nologin, bin, faillog, lastlog, newgrp, sg)
|
||||
|
||||
# dpkg -L passwd | grep bin | xargs -L 1 basename | tr "\\n" ","
|
||||
# dpkg -L login | grep bin | xargs ls -ld | grep -v '^d' | awk '{print $9}' | xargs -L 1 basename | tr "\\n" ","
|
||||
- macro: login_binaries
|
||||
condition: proc.name in (login, systemd-logind, su, nologin, faillog, lastlog, newgrp, sg)
|
||||
|
||||
# dpkg -L passwd | grep bin | xargs ls -ld | grep -v '^d' | awk '{print $9}' | xargs -L 1 basename | tr "\\n" ","
|
||||
- macro: passwd_binaries
|
||||
condition: >
|
||||
proc.name in (sbin, shadowconfig, sbin, grpck, pwunconv, grpconv, pwck,
|
||||
proc.name in (shadowconfig, grpck, pwunconv, grpconv, pwck,
|
||||
groupmod, vipw, pwconv, useradd, newusers, cppw, chpasswd, usermod,
|
||||
groupadd, groupdel, grpunconv, chgpasswd, userdel, bin, chage, chsh,
|
||||
groupadd, groupdel, grpunconv, chgpasswd, userdel, chage, chsh,
|
||||
gpasswd, chfn, expiry, passwd, vigr, cpgr)
|
||||
|
||||
# repoquery -l shadow-utils | grep bin | xargs -L 1 basename | tr "\\n" ","
|
||||
# repoquery -l shadow-utils | grep bin | xargs ls -ld | grep -v '^d' | awk '{print $9}' | xargs -L 1 basename | tr "\\n" ","
|
||||
- macro: shadowutils_binaries
|
||||
condition: >
|
||||
proc.name in (chage, gpasswd, lastlog, newgrp, sg, adduser, chpasswd,
|
||||
groupadd, groupdel, groupmems, groupmod, grpck, grpconv, grpunconv,
|
||||
newusers, pwck, pwconv, pwunconv, useradd, userdel, usermod, vigr, vipw)
|
||||
proc.name in (chage, gpasswd, lastlog, newgrp, sg, adduser, deluser, chpasswd,
|
||||
groupadd, groupdel, addgroup, delgroup, groupmems, groupmod, grpck, grpconv, grpunconv,
|
||||
newusers, pwck, pwconv, pwunconv, useradd, userdel, usermod, vigr, vipw, unix_chkpwd)
|
||||
|
||||
- macro: sysdigcloud_binaries
|
||||
condition: proc.name in (setup-backend, dragent)
|
||||
|
||||
- macro: sysdigcloud_binaries_parent
|
||||
condition: proc.pname in (setup-backend, dragent)
|
||||
|
||||
- macro: docker_binaries
|
||||
condition: proc.name in (docker, exe)
|
||||
@ -103,25 +115,33 @@
|
||||
- macro: db_server_binaries
|
||||
condition: proc.name in (mysqld)
|
||||
|
||||
- macro: server_binaries
|
||||
condition: http_server_binaries or db_server_binaries or docker_binaries or proc.name in (sshd)
|
||||
- macro: db_server_binaries_parent
|
||||
condition: proc.pname in (mysqld)
|
||||
|
||||
- macro: server_binaries
|
||||
condition: (http_server_binaries or db_server_binaries or docker_binaries or proc.name in (sshd))
|
||||
|
||||
# The truncated dpkg-preconfigu is intentional, process names are
|
||||
# truncated at the sysdig level.
|
||||
- macro: package_mgmt_binaries
|
||||
condition: proc.name in (dpkg, rpm)
|
||||
condition: proc.name in (dpkg, dpkg-preconfigu, rpm, yum)
|
||||
|
||||
# A canonical set of processes that run other programs with different
|
||||
# privileges or as a different user.
|
||||
- macro: userexec_binaries
|
||||
condition: proc.name in (sudo, su)
|
||||
|
||||
- macro: user_mgmt_binaries
|
||||
condition: (login_binaries or passwd_binaries or shadowutils_binaries)
|
||||
|
||||
- macro: system_binaries
|
||||
condition: coreutils_binaries or adduser_binaries or login_binaries or passwd_binaries or shadowutils_binaries
|
||||
condition: (coreutils_binaries or user_mgmt_binaries)
|
||||
|
||||
- macro: mail_binaries
|
||||
condition: proc.name in (sendmail, postfix, procmail)
|
||||
condition: proc.name in (sendmail, sendmail-msp, postfix, procmail)
|
||||
|
||||
- macro: sensitive_files
|
||||
condition: fd.name contains /etc/shadow or fd.name = /etc/sudoers or fd.directory = /etc/sudoers.d or fd.directory = /etc/pam.d or fd.name = /etc/pam.conf
|
||||
condition: (fd.name contains /etc/shadow or fd.name = /etc/sudoers or fd.directory = /etc/sudoers.d or fd.directory = /etc/pam.d or fd.name = /etc/pam.conf)
|
||||
|
||||
# Indicates that the process is new. Currently detected using time
|
||||
# since process was started, using a threshold of 5 seconds.
|
||||
@ -130,7 +150,7 @@
|
||||
|
||||
# Network
|
||||
- macro: inbound
|
||||
condition: (syscall.type=listen and evt.dir=>) or (syscall.type=accept and evt.dir=<)
|
||||
condition: ((syscall.type=listen and evt.dir=>) or (syscall.type=accept and evt.dir=<))
|
||||
|
||||
# Currently sendto is an ignored syscall, otherwise this could also check for (syscall.type=sendto and evt.dir=>)
|
||||
- macro: outbound
|
||||
@ -141,7 +161,7 @@
|
||||
|
||||
# Ssh
|
||||
- macro: ssh_error_message
|
||||
condition: evt.arg.data contains "Invalid user" or evt.arg.data contains "preauth"
|
||||
condition: (evt.arg.data contains "Invalid user" or evt.arg.data contains "preauth" or evt.arg.data contains "Failed password")
|
||||
|
||||
# System
|
||||
- macro: modules
|
||||
@ -149,9 +169,9 @@
|
||||
- macro: container
|
||||
condition: container.id != host
|
||||
- macro: interactive
|
||||
condition: (proc.aname=sshd and proc.name != sshd) or proc.name=systemd-logind
|
||||
condition: ((proc.aname=sshd and proc.name != sshd) or proc.name=systemd-logind)
|
||||
- macro: syslog
|
||||
condition: fd.name = /dev/log
|
||||
condition: fd.name in (/dev/log, /run/systemd/journal/syslog)
|
||||
- macro: cron
|
||||
condition: proc.name in (cron, crond)
|
||||
- macro: parent_cron
|
||||
@ -169,32 +189,32 @@
|
||||
|
||||
- rule: write_binary_dir
|
||||
desc: an attempt to write to any file below a set of binary directories
|
||||
condition: evt.dir = > and open_write and bin_dir
|
||||
condition: evt.dir = < and open_write and not package_mgmt_binaries and bin_dir
|
||||
output: "File below a known binary directory opened for writing (user=%user.name command=%proc.cmdline file=%fd.name)"
|
||||
priority: WARNING
|
||||
|
||||
- rule: write_etc
|
||||
desc: an attempt to write to any file below /etc
|
||||
condition: evt.dir = > and open_write and etc_dir
|
||||
condition: evt.dir = < and open_write and not shadowutils_binaries and not sysdigcloud_binaries_parent and not package_mgmt_binaries and etc_dir
|
||||
output: "File below /etc opened for writing (user=%user.name command=%proc.cmdline file=%fd.name)"
|
||||
priority: WARNING
|
||||
|
||||
- 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.
|
||||
condition: open_read and not server_binaries and not userexec_binaries and not proc.name in (iptables, ps, systemd-logind, lsb_release, check-new-relea, dumpe2fs, accounts-daemon, bash) and not cron and sensitive_files
|
||||
condition: open_read and not user_mgmt_binaries and not userexec_binaries and not proc.name in (iptables, ps, lsb_release, check-new-relea, dumpe2fs, accounts-daemon, bash, sshd) and not cron and sensitive_files
|
||||
output: "Sensitive file opened for reading by non-trusted program (user=%user.name command=%proc.cmdline file=%fd.name)"
|
||||
priority: WARNING
|
||||
|
||||
- rule: read_sensitive_file_trusted_after_startup
|
||||
desc: 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: open_read and server_binaries and not proc_is_new and sensitive_files
|
||||
condition: open_read and server_binaries and not proc_is_new and sensitive_files and proc.name!="sshd"
|
||||
output: "Sensitive file opened for reading by trusted program after startup (user=%user.name command=%proc.cmdline file=%fd.name)"
|
||||
priority: WARNING
|
||||
|
||||
- rule: db_program_spawn_process
|
||||
desc: a database-server related program spawning a new process after startup. This shouldn\'t occur and is a follow on from some SQL injection attacks.
|
||||
condition: db_server_binaries and not proc_is_new and spawn_process
|
||||
output: "Database-related program spawned new process after startup (user=%user.name command=%proc.cmdline)"
|
||||
- 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: db_server_binaries_parent and not db_server_binaries and spawned_process
|
||||
output: "Database-related program spawned process other than itself (user=%user.name program=%proc.cmdline parent=%proc.pname)"
|
||||
priority: WARNING
|
||||
|
||||
- rule: modify_binary_dirs
|
||||
@ -218,11 +238,12 @@
|
||||
# output: "Loaded .so from unexpected dir (%user.name %proc.name %evt.dir %evt.type %evt.args %fd.name)"
|
||||
# priority: WARNING
|
||||
|
||||
- rule: syscall_returns_eaccess
|
||||
desc: any system call that returns EACCESS. This is not always a strong indication of a problem, hence the INFO priority.
|
||||
condition: evt.res = EACCESS
|
||||
output: "System call returned EACCESS (user=%user.name command=%proc.cmdline syscall=%evt.type args=%evt.args)"
|
||||
priority: INFO
|
||||
# Temporarily disabling this rule as it's tripping over https://github.com/draios/sysdig/issues/598
|
||||
# - rule: syscall_returns_eaccess
|
||||
# desc: any system call that returns EACCESS. This is not always a strong indication of a problem, hence the INFO priority.
|
||||
# condition: evt.res = EACCESS
|
||||
# output: "System call returned EACCESS (user=%user.name command=%proc.cmdline syscall=%evt.type args=%evt.args)"
|
||||
# priority: INFO
|
||||
|
||||
- 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.
|
||||
@ -232,7 +253,7 @@
|
||||
|
||||
- rule: run_shell_untrusted
|
||||
desc: an attempt to spawn a shell by a non-shell program. Exceptions are made for trusted binaries.
|
||||
condition: proc.name = bash and evt.dir=< and evt.type=execve and proc.pname exists and not parent_cron and not proc.pname in (bash, sshd, sudo, docker, su, tmux, screen, emacs, systemd, flock, fs-bash, nginx, monit, supervisord)
|
||||
condition: not container and proc.name = bash and spawned_process and proc.pname exists and not parent_cron and not proc.pname in (bash, sshd, sudo, docker, su, tmux, screen, emacs, systemd, login, flock, fbash, nginx, monit, supervisord, dragent)
|
||||
output: "Shell spawned by untrusted binary (user=%user.name shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline)"
|
||||
priority: WARNING
|
||||
|
||||
@ -243,13 +264,13 @@
|
||||
|
||||
- rule: system_user_interactive
|
||||
desc: an attempt to run interactive commands by a system (i.e. non-login) user
|
||||
condition: spawn_process and system_users and interactive
|
||||
condition: spawned_process and system_users and interactive
|
||||
output: "System user ran an interactive command (user=%user.name command=%proc.cmdline)"
|
||||
priority: WARNING
|
||||
|
||||
- rule: run_shell_in_container
|
||||
desc: an attempt to spawn a shell by a non-shell program in a container. Container entrypoints are excluded.
|
||||
condition: container and proc.name = bash and evt.dir=< and evt.type=execve and proc.pname exists and not proc.pname in (bash, docker)
|
||||
desc: a shell was spawned by a non-shell program in a container. Container entrypoints are excluded.
|
||||
condition: container and proc.name = bash and spawned_process and proc.pname exists and not proc.pname in (bash, docker)
|
||||
output: "Shell spawned in a container other than entrypoint (user=%user.name container_id=%container.id container_name=%container.name shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline)"
|
||||
priority: WARNING
|
||||
|
||||
@ -260,22 +281,26 @@
|
||||
output: "Known system binary sent/received network traffic (user=%user.name command=%proc.cmdline connection=%fd.name)"
|
||||
priority: WARNING
|
||||
|
||||
- rule: ssh_error_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
|
||||
# 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_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
|
||||
|
||||
# sshd, sendmail-msp, sendmail 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. user "root" is also excluded, as setuid calls typically involve dropping privileges.
|
||||
condition: evt.type=setuid and evt.dir=> and not user.name=root and not userexec_binaries
|
||||
condition: evt.type=setuid and evt.dir=> and not user.name=root and not userexec_binaries and not proc.name in (sshd, sendmail-msp, sendmail)
|
||||
output: "Unexpected setuid call by non-sudo, non-root program (user=%user.name command=%proc.cmdline uid=%evt.arg.uid)"
|
||||
priority: WARNING
|
||||
|
||||
- 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.
|
||||
condition: spawn_process and not proc.name in (su, sudo) and not container and (adduser_binaries or login_binaries or passwd_binaries or shadowutils_binaries)
|
||||
output: "User management binary command run outside of container (user=%user.name command=%proc.cmdline)"
|
||||
condition: spawned_process and not proc.name in (su, sudo) and not container and user_mgmt_binaries and not parent_cron and not proc.pname in (systemd, run-parts)
|
||||
output: "User management binary command run outside of container (user=%user.name command=%proc.cmdline parent=%proc.pname)"
|
||||
priority: WARNING
|
||||
|
||||
# (we may need to add additional checks against false positives, see: https://bugs.launchpad.net/ubuntu/+source/rkhunter/+bug/86153)
|
||||
@ -285,17 +310,17 @@
|
||||
output: "File created below /dev by untrusted program (user=%user.name command=%proc.cmdline file=%fd.name)"
|
||||
priority: WARNING
|
||||
|
||||
# fs-bash is a restricted version of bash suitable for use in curl <curl> | sh installers.
|
||||
# fbash is a small shell script that runs bash, and is suitable for use in curl <curl> | fbash installers.
|
||||
- rule: installer_bash_starts_network_server
|
||||
desc: an attempt by any program that is a child of fs-bash to start listening for network connections
|
||||
condition: evt.type=listen and proc.aname=fs-bash
|
||||
output: "Unexpected listen call by a child process of fs-bash (command=%proc.cmdline)"
|
||||
desc: an attempt by any program that is a child of fbash to start listening for network connections
|
||||
condition: evt.type=listen and proc.aname=fbash
|
||||
output: "Unexpected listen call by a child process of fbash (command=%proc.cmdline)"
|
||||
priority: WARNING
|
||||
|
||||
- rule: installer_bash_starts_session
|
||||
desc: an attempt by any program that is a child of fs-bash to start a new session (process group)
|
||||
condition: evt.type=setsid and proc.aname=fs-bash
|
||||
output: "Unexpected setsid call by a child process of fs-bash (command=%proc.cmdline)"
|
||||
desc: an attempt by any program that is a child of fbash to start a new session (process group)
|
||||
condition: evt.type=setsid and proc.aname=fbash
|
||||
output: "Unexpected setsid call by a child process of fbash (command=%proc.cmdline)"
|
||||
priority: WARNING
|
||||
|
||||
###########################
|
||||
|
9
test/utils/run_sysdig.sh
Normal file
9
test/utils/run_sysdig.sh
Normal file
@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Run sysdig excluding all events that aren't used by falco and also
|
||||
# excluding other high-volume events that aren't essential. This
|
||||
# results in smaller trace files.
|
||||
|
||||
# The remaining arguments are taken from the command line.
|
||||
|
||||
exec sudo sysdig not evt.type in '(mprotect,brk,mq_timedreceive,mq_receive,mq_timedsend,mq_send,getrusage,procinfo,rt_sigprocmask,rt_sigaction,ioctl,clock_getres,clock_gettime,clock_nanosleep,clock_settime,close,epoll_create,epoll_create1,epoll_ctl,epoll_pwait,epoll_wait,eventfd,fcntl,fcntl64,fstat,fstat64,fstatat64,fstatfs,fstatfs64,futex,getitimer,gettimeofday,ioprio_get,ioprio_set,llseek,lseek,lstat,lstat64,mmap,mmap2,munmap,nanosleep,poll,ppoll,pread,pread64,preadv,procinfo,pselect6,pwrite,pwrite64,pwritev,read,readv,recv,recvfrom,recvmmsg,recvmsg,sched_yield,select,send,sendfile,sendfile64,sendmmsg,sendmsg,sendto,setitimer,settimeofday,shutdown,splice,stat,stat64,statfs,statfs64,switch,tee,timer_create,timer_delete,timerfd_create,timerfd_gettime,timerfd_settime,timer_getoverrun,timer_gettime,timer_settime,wait4,write,writev) and user.name!=ec2-user' $@
|
Loading…
Reference in New Issue
Block a user