From abc79fb548f9d925ffdeffe65f3bd32b79ab70f4 Mon Sep 17 00:00:00 2001 From: Lorenzo Fontana Date: Wed, 7 Apr 2021 13:40:20 +0200 Subject: [PATCH] update(rules): revert exceptions in default ruleset Exceptions have been introduced in commit 64a231b9623b59955ca3ec2d42466c9b26a802ec The feature itself is very useful for more complex environments where the simple conditions are difficult to handle. However, many users reported that they find them difficult to understand so we are doing a rollback of them in the default ruleset in favor of the syntax without exceptions. Signed-off-by: Lorenzo Fontana --- rules/falco_rules.yaml | 1334 ++++++++++++++++++---------------------- 1 file changed, 604 insertions(+), 730 deletions(-) diff --git a/rules/falco_rules.yaml b/rules/falco_rules.yaml index a7fc23ad..765962bf 100644 --- a/rules/falco_rules.yaml +++ b/rules/falco_rules.yaml @@ -15,8 +15,10 @@ # limitations under the License. # -# Falco engine 8 supports exception properties on rules. -- required_engine_version: 8 +# The latest Falco Engine version is 8 if you want to +# use exceptions. However the default rules file does not +# use them so we stick with 7 for compatibility. +- required_engine_version: 7 # Currently disabled as read/write are ignored syscalls. The nearly # similar open_write/open_read check for files being opened for @@ -208,6 +210,9 @@ - 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-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, @@ -228,6 +233,9 @@ 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) @@ -343,17 +351,12 @@ # 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 ..." -# -# If at all possible, use the rule exceptions instead. - 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 - exceptions: - - name: allowed_ssh_ipaddrs - fields: fd.sip output: Disallowed SSH Connection (command=%proc.cmdline connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository) priority: NOTICE tags: [network, mitre_remote_service] @@ -381,20 +384,10 @@ - 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: > - consider_all_outbound_conns and outbound - exceptions: - - name: allowed_outbound_ipaddrs - fields: fd.sip - values: - - allowed_outbound_destination_ipaddrs - - name: allowed_outbound_networks - fields: fd.snet - values: - - allowed_outbound_destination_networks - - name: allowed_outbound_domains - fields: fd.sip.name - values: - - allowed_outbound_destination_domains + consider_all_outbound_conns and 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))) output: Disallowed outbound connection destination (command=%proc.cmdline connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository) priority: NOTICE tags: [network] @@ -414,20 +407,10 @@ - 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: > - consider_all_inbound_conns and inbound - exceptions: - - name: allowed_inbound_ipaddrs - fields: fd.cip - values: - - allowed_inbound_source_ipaddrs - - name: allowed_inbound_networks - fields: fd.cnet - values: - - allowed_inbound_source_networks - - name: allowed_inbound_domains - fields: fd.cip.name - values: - - allowed_inbound_source_domains + consider_all_inbound_conns and 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))) output: Disallowed inbound connection source (command=%proc.cmdline connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository) priority: NOTICE tags: [network] @@ -457,9 +440,6 @@ - list: shell_config_directories items: [/etc/zsh] -- list: lvprogs_binaries - items: [dmeventd, lvcreate, pvscan, lvs] - - rule: Modify Shell Configuration File desc: Detect attempt to modify shell configuration files condition: > @@ -469,10 +449,6 @@ fd.directory in (shell_config_directories)) and not proc.name in (shell_binaries) and not exe_running_docker_save - exceptions: - - name: known_shell_conf_writers - fields: [proc.name, fd.name] - comps: [=, contains] output: > a shell configuration file has been modified (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pcmdline=%proc.pcmdline file=%fd.name container_id=%container.id image=%container.image.repository) priority: @@ -495,10 +471,6 @@ fd.name in (shell_config_files) or fd.directory in (shell_config_directories)) and (not proc.name in (shell_binaries)) - exceptions: - - name: known_shell_conf_readers - fields: [proc.name, fd.name] - comps: [=, contains] output: > a shell configuration file was read by a non-shell program (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline file=%fd.name container_id=%container.id image=%container.image.repository) priority: @@ -518,10 +490,6 @@ (spawned_process and proc.name = "crontab")) and consider_all_cron_jobs and not user_known_cron_jobs - exceptions: - - name: known_cron_writers - fields: [proc.name, fd.name] - comps: [=, contains] output: > Cron jobs were scheduled to run (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline file=%fd.name container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag) @@ -570,12 +538,25 @@ - macro: system_users condition: user.name in (bin, daemon, games, lp, mail, nobody, sshd, sync, uucp, www-data) +- macro: parent_python_running_sdchecks + condition: > + (proc.pname in (python, python2.7) and + (proc.pcmdline contains /opt/draios/bin/sdchecks)) + +- macro: python_running_sdchecks + condition: > + (proc.name in (python, python2.7) and + (proc.cmdline contains /opt/draios/bin/sdchecks)) + - 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) + - macro: ansible_running_python condition: (proc.name in (python, pypy, python3) and proc.cmdline contains ansible) @@ -638,16 +619,53 @@ ((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") +- macro: perl_running_updmap + condition: (proc.cmdline startswith "perl /usr/bin/updmap") + +- macro: perl_running_centrifydc + condition: (proc.cmdline startswith "perl /usr/share/centrifydc") + +- macro: runuser_reading_pam + condition: (proc.name=runuser and fd.directory=/etc/pam.d) + # CIS Linux Benchmark program - macro: linux_bench_reading_etc_shadow condition: ((proc.aname[2]=linux-bench and @@ -663,6 +681,9 @@ ((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] @@ -673,14 +694,69 @@ 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] @@ -693,15 +769,27 @@ - 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: 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" @@ -709,24 +797,51 @@ 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] @@ -761,12 +876,6 @@ and not package_mgmt_ancestor_procs and not exe_running_docker_save and not user_known_update_package_registry - exceptions: - - name: package_repo_filenames - fields: [proc.name, fd.name] - comps: [=, contains] - - name: package_repo_dirs - fields: [proc.name, fd.directory] output: > Repository files get updated (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pcmdline=%proc.pcmdline file=%fd.name newpath=%evt.arg.newpath container_id=%container.id image=%container.image.repository) priority: @@ -787,14 +896,6 @@ and not python_running_get_pip and not python_running_ms_oms and not user_known_write_below_binary_dir_activities - exceptions: - - name: proc_names - fields: proc.name - comps: in - values: [package_mgmt_binaries] - - name: known_bin_writers - fields: [proc.name, fd.name] - comps: [=, contains] output: > File below a known binary directory opened for writing (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository) @@ -811,6 +912,13 @@ - macro: user_ssh_directory condition: (fd.name glob '/home/*/.ssh/*') +# 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) @@ -833,26 +941,14 @@ 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 - exceptions: - - name: proc_names - fields: proc.name - comps: in - values: [package_mgmt_binaries] - - name: known_writer_prefix - fields: [proc.name, fd.name] - comps: [=, startswith] - values: - - [update-ssh-keys, /home/core/.ssh] - - name: known_writer_prefix_substring - fields: [proc.name, fd.name, fd.name] - comps: [=, startswith, contains] - values: - - [google_accounts, /home, .ssh] - - [cloud-init, /home, .ssh] output: > File below a monitored directory opened for writing (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository) @@ -876,10 +972,6 @@ (user_ssh_directory or fd.name startswith /root/.ssh) and not user_known_read_ssh_information_activities and not proc.name in (ssh_binaries)) - exceptions: - - name: known_ssh_reader - fields: [proc.name, fd.name] - comps: [=, contains] output: > ssh-related file/directory read by non-ssh program (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline container_id=%container.id image=%container.image.repository) @@ -889,15 +981,43 @@ - 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] +- 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 @@ -910,6 +1030,11 @@ (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" @@ -917,6 +1042,41 @@ 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 @@ -924,18 +1084,58 @@ 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=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. +# /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. @@ -951,207 +1151,111 @@ 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) 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 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 - 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 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)" - exceptions: - - name: proc_names - fields: proc.name - values: [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] - - name: proc_pnames - fields: proc.pname - values: [sysdigcloud_binaries, mail_config_binaries, hddtemp.postins, - sshkit_script_binaries, locales.postins, deb_binaries, dhcp_binaries] - - name: dirs - fields: fd.name - comps: pmatch - values: [safe_etc_dirs] - - name: files - fields: fd.name - values: [/etc/container_environment.sh, /etc/container_environment.json, /etc/motd, /etc/motd.svc] - - name: proc_file - fields: [proc.name, fd.name] - comps: [in, in] - values: - - [[qualys-cloud-ag], [/etc/qualys/cloud-agent/qagent-log.conf]] - - [[add-shell], [/etc/shells.tmp]] - - [[htpasswd], [/etc/nginx/.htpasswd]] - - [[java], [/etc/.java/.systemPrefs/.system.lock]] - - [[php_handlers_co], [/etc/psa/php_versions.json]] - - [[NetworkWatcherA], [/etc/init.d/AzureNetworkWatcherAgent]] - - [[navdefutil], [/etc/symc-defutils.conf]] - - [[brandbot], [/etc/os-release]] - - [[keepalived], [/etc/keepalived/keepalived.conf]] - - [[update-haproxy-,haproxy_reload.], [/etc/openvpn/client.map]] - - [[start-fluentd], [/etc/fluent/fluent.conf, /etc/td-agent/td-agent.conf]] - - [[run-redis, redis-launcher.], [/etc/redis.conf]] - - name: proc_file_prefix - fields: [proc.name, fd.name] - comps: [in, startswith] - values: - - [[sed], /etc/sed] - - [[httpd], /etc/httpd/] - - [[GetLinuxOS.sh], /etc/opt/microsoft/scx] - - [[update-texmf], /etc/texmf] - - [[slapadd], /etc/ldap] - - [[symcfgd], /etc/symantec] - - [[userhelper], /etc/security] - - [[iscsiadm], /etc/iscsi] - - [[pilot-agent], /etc/istio] - - [[calico-node], /etc/calico] - - [[prometheus-conf], /etc/prometheus/config_out] - - [[oc], /etc/origin/node] - - [[plesk_binaries], /etc/sw/keys] - - [[supervise,svc], /etc/sb/] - - [[openvpn,openvpn-entrypo], /etc/openvpn] - - [[semodule,genhomedircon,sefcontext_comp], /etc/selinux] - - [[lvprogs_binaries], /etc/lvm/archive] - - [[lvprogs_binaries], /etc/lvm/backup] - - [[lvprogs_binaries], /etc/lvm/cache] - - [[nginx,nginx-ingress-c,nginx-ingress], /etc/nginx] - - [[nginx,nginx-ingress-c,nginx-ingress], /etc/ingress-controller] - - [[adjoin,addns], /etc/krb5] - - [[run-redis, redis-launcher.], /etc/redis/] - - [[update-haproxy-,haproxy_reload.], /etc/haproxy] - - [[start-mysql.sh, run-mysqld], /etc/mysql] - - [[multipath], /etc/multipath/] - - name: proc_directory - fields: [proc.name, fd.directory] - comps: [in, in] - values: - - [[git-remote-http], [/etc/pki/nssdb]] - - [[update-xmlcatal], [/etc/xml]] - - [[ovsdb-server], [/etc/openvswitch]] - - [[curl], [/etc/pki/nssdb]] - - [[rabbitmq-server], [/etc/rabbitmq]] - - [[start-ipsec.sh], [/etc/ipsec]] - - [[ufw], [/etc/ufw]] - - [[macompatsvc], [/etc/cma.d]] - - [[start-mysql.sh, run-mysqld], [/etc/my.cnf.d]] - - name: pname_file - fields: [proc.pname, fd.name] - comps: [in, in] - values: - - [[update-haproxy-,haproxy_reload,haproxy_reload.], [/etc/openvpn/client.map]] - - name: pname_file_prefix - fields: [proc.pname, fd.name] - comps: [in, startswith] - values: - - [[run-openldap.sh], /etc/openldap] - - [[start-mysql.sh], /etc/mysql] - - [[update-haproxy-,haproxy_reload.], /etc/haproxy] - - name: pname_directory - fields: [proc.pname, fd.directory] - comps: [in, in] - values: - - [[start-mysql.sh], [/etc/my.cnf.d]] - - name: pname_prefix_file_prefix - fields: [proc.pname, fd.name] - comps: [startswith, startswith] - values: - - ["bash /var/lib/waagent/", /etc/azure] - - [automount, /etc/mtab] - - name: proc_pname_file - fields: [proc.name, proc.pname, fd.name] - comps: [in, in, startswith] - values: - - [[urlgrabber-ext-], [yum, yum-cron, repoquery], /etc/pkt/nssdb or fd.name startswith /etc/pki/nssdb] - - [[urlgrabber-ext-], [yum, yum-cron, repoquery], /etc/pki/nssdb] - - [[trust], [update-ca-trust], /etc/pki] - - name: cmdline_file - fields: [proc.cmdline, fd.name] - comps: [in, in] - values: - - [["bash /usr/sbin/start-cron"], [/etc/security/pam_env.conf]] - - name: cmdline_file_prefix - fields: [proc.cmdline, fd.name] - comps: [in, startswith] - values: - - [["bash /usr/sbin/start-cron"], /etc/security/pam_env.conf] - - [["se_supervisor.p /opt/avi/scripts/se_supervisor.py -d"], /etc/ssh/known_host_] - - [["se_supervisor.p /opt/avi/scripts/se_supervisor.py -d"], /etc/ssh/ssh_monitor_config_] - - [["se_supervisor.p /opt/avi/scripts/se_supervisor.py -d"], /etc/ssh/ssh_config_] - - name: cmdline_prefix_file - fields: [proc.cmdline, fd.name] - comps: [startswith, in] - values: - - ["bash -hB /usr/lib/plesk-9.0/services/webserver.apache configure", ["/etc/apache2/apache2.conf.tmp"]] - - ["java LiveUpdate", [/etc/liveupdate.conf]] - - ["java LiveUpdate", [/etc/Product.Catalog.JavaLiveUpdate]] - - name: cmdline_prefix_file_prefix - fields: [proc.cmdline, fd.name] - comps: [startswith, startswith] - values: - - ["bash /usr/local/lib/pki/pki-realm", /etc/pki/realms] - - ["python /opt/datadog-agent", "/etc/dd-agent"] - - ["entrypoint.sh /entrypoint.sh datadog start", "/etc/dd-agent"] - - ["agent.py /opt/datadog-agent", "/etc/dd-agent"] - - ["nodejs /opt/countly/bin", /etc/nginx] - - name: pcmdline_prefix_file_prefix - fields: [proc.pcmdline, fd.name] - comps: [startswith, startswith] - values: - - ["bash /var/lib/waagent/", /etc/azure] - - ["chef-client /opt/gitlab", /etc/gitlab] - - name: proc_container_dir - fields: [proc.name, container.image.repository, fd.directory] - comps: [in, in, in] - values: - - [[toolbox.sh], [rook/toolbox], [/etc/ceph]] - - name: proc_container_file - fields: [proc.name, container.image.repository, fd.name] - comps: [in, in, in] - values: - - [[apiserver], [docker/ucp-agent], [/etc/authorization_config.cfg]] - - name: proc_container_prefix - fields: [proc.name, container.image.repository, fd.name] - comps: [in, in, startswith] - values: - - [[start_runit, cp], [gcr.io/projectcalico-org/node], /etc/calico] - - [[sed], [gcr.io/projectcalico-org/cni], /etc/calico] - - [[checkpoint], ["coreos/pod-checkpointer"], "/etc/kubernetes"] priority: ERROR tags: [filesystem, mitre_persistence] @@ -1163,6 +1267,43 @@ - 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 @@ -1177,94 +1318,40 @@ - 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 - exceptions: - - name: files - fields: fd.name - values: [known_root_files] - - name: dirs - fields: fd.directory - comps: pmatch - values: [known_root_directories] - - name: prefixes - fields: [fd.name] - comps: [startswith] - values: - - [/root/orcexec.] - - [/root/.m2] - - [/root/.npm] - - [/root/.pki] - - [/root/.ivy2] - - [/root/.config/Cypress] - - [/root/.config/pulse] - - [/root/.config/configstore] - - [/root/jenkins/workspace] - - [/root/.jenkins] - - [/root/.cache] - - [/root/.sbt] - - [/root/.java] - - [/root/.glide] - - [/root/.sonar] - - [/root/.v8flag] - - [/root/infaagent] - - [/root/.local/lib/python] - - [/root/.pm2] - - [/root/.gnupg] - - [/root/.pgpass] - - [/root/.theano] - - [/root/.gradle] - - [/root/.android] - - [/root/.ansible] - - [/root/.crashlytics] - - [/root/.dbus] - - [/root/.composer] - - [/root/.gconf] - - [/root/.nv] - - [/root/.local/share/jupyter] - - [/root/oradiag_root] - - [/root/workspace] - - [/root/jvm] - - [/root/.node-gyp] - - name: proc_file - fields: [proc.name, fd.name] - comps: [in, in] - values: - - [[gugent], [GuestAgent.log]] - - [[dse-entrypoint], [/root/tmp__]] - - [[galley], [known_istio_files]] - - name: proc_directory - fields: [proc.name, fd.directory] - comps: [in, in] - values: - - [[rpm], [/root/.rpmdb]] - - [[mysqlsh], [/root/.mysqlsh]] - - name: proc_file_prefix - fields: [proc.name, fd.name] - comps: [in, startswith] - values: - - [[airflow], /root/airflow] - - [[chef-client], /root/.chef] - - [[kubectl, oc], /root/.kube] - - name: cmdline_file - fields: [proc.cmdline, fd.name] - comps: [in, in] - values: - - [["runc:[1:CHILD] init"], [/exec.fifo]] output: "File below / or /root opened for writing (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline parent=%proc.pname file=%fd.name program=%proc.name container_id=%container.id image=%container.image.repository)" priority: ERROR tags: [filesystem, mitre_persistence] @@ -1281,10 +1368,6 @@ 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 - exceptions: - - name: known_sensitive_reader - fields: [proc.name, fd.name] - comps: [=, contains] output: > Sensitive file opened for reading by trusted program after startup (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline parent=%proc.pname file=%fd.name parent=%proc.pname gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository) @@ -1325,6 +1408,12 @@ condition: > sensitive_files and open_read 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, + vpn_binaries, mail_config_binaries, nomachine_binaries, sshkit_script_binaries, + in.proftpd, mandb, salt-minion, postgres_mgmt_binaries, + google_oslogin_ + ) and not cmp_cp_by_passwd and not ansible_running_python and not proc.cmdline contains /usr/bin/mandb @@ -1333,32 +1422,13 @@ and not run_by_google_accounts_daemon and not user_read_sensitive_file_conditions and not perl_running_plesk + and not perl_running_updmap + and not veritas_driver_script + and not perl_running_centrifydc + and not runuser_reading_pam and not linux_bench_reading_etc_shadow and not user_known_read_sensitive_files_activities and not user_read_sensitive_file_containers - exceptions: - - name: proc_names - fields: proc.name - comps: in - values: [user_mgmt_binaries, userexec_binaries, package_mgmt_binaries, - cron_binaries, read_sensitive_file_binaries, shell_binaries, hids_binaries, - vpn_binaries, mail_config_binaries, nomachine_binaries, sshkit_script_binaries, - in.proftpd, mandb, salt-minion, postgres_mgmt_binaries, - google_oslogin_] - - name: cmdline - fields: [proc.cmdline] - ops: [startswith] - values: - - ["perl /usr/bin/updmap"] - - ["perl /opt/VRTSsfmh/bin/mh_driver.pl"] - - ["perl /usr/share/centrifydc"] - - name: proc_directory - fields: [proc.name, fd.directory] - values: - - [runuser, /etc/pam.d] - - name: proc_file_prefix - fields: [proc.name, fd.name] - comps: [in, startswith] output: > Sensitive file opened for reading by non-trusted program (user=%user.name user_loginuid=%user.loginuid program=%proc.name command=%proc.cmdline 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) @@ -1379,26 +1449,30 @@ 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 - exceptions: - - name: proc_names - fields: proc.name - comps: in - values: [rpm_binaries, openscap_rpm_binaries, salt-minion] - - name: proc_file_prefix - fields: [proc.name, fd.name] - comps: [in, startswith] output: "Rpm database opened for writing by a non-rpm program (command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline container_id=%container.id image=%container.image.repository)" priority: ERROR tags: [filesystem, software_mgmt, mitre_persistence] +- 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") + - macro: redis_running_prepost_scripts condition: (proc.aname[2]=redis-server and (proc.cmdline contains "redis-server.post-up.d" or proc.cmdline contains "redis-server.pre-up.d")) +- macro: rabbitmq_running_scripts + condition: > + (proc.pname=beam.smp and + (proc.cmdline startswith "sh -c exec ps" or + proc.cmdline startswith "sh -c exec inet_gethost" or + proc.cmdline= "sh -s unix:cmd" or + proc.cmdline= "sh -c exec /bin/sh -s unix:cmd 2>&1")) + - macro: rabbitmqctl_running_scripts condition: (proc.aname[2]=rabbitmqctl and proc.cmdline startswith "sh -c ") @@ -1416,13 +1490,8 @@ 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 - exceptions: - - name: pname_cmdline - fields: [proc.pname, proc.cmdline] - comps: [in, startswith] - values: - - [[postgres], "sh -c envdir /etc/wal-e.d/env /usr/local/bin/wal-e"] output: > Database-related program spawned process other than itself (user=%user.name user_loginuid=%user.loginuid program=%proc.cmdline parent=%proc.pname container_id=%container.id image=%container.image.repository) @@ -1434,17 +1503,7 @@ - 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 exe_running_docker_save - and not user_known_modify_bin_dir_activities - exceptions: - - name: proc_names - fields: proc.name - comps: in - values: [package_mgmt_binaries] - - name: proc_file_prefix - fields: [proc.name, fd.name] - comps: [in, startswith] + 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 pcmdline=%proc.pcmdline operation=%evt.type file=%fd.name %evt.args container_id=%container.id image=%container.image.repository) @@ -1459,16 +1518,9 @@ 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 - exceptions: - - name: proc_names - fields: proc.name - comps: in - values: [package_mgmt_binaries] - - name: proc_file_prefix - fields: [proc.name, fd.name] - comps: [in, startswith] output: > Directory below known binary directory created (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline directory=%evt.arg.path container_id=%container.id image=%container.image.repository) @@ -1487,6 +1539,12 @@ - list: network_plugin_binaries items: [aws-cni, azure-vnet] +- macro: calico_node + condition: (container.image.repository endswith calico/node and proc.name=calico-node) + +- 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 @@ -1494,44 +1552,20 @@ 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 python_running_sdchecks + 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 - exceptions: - - name: proc_names - fields: proc.name - comps: in - values: [sysdigcloud_binaries, sysdig, calico, oci-umount, - cilium-cni, network_plugin_binaries, - user_known_change_thread_namespace_binaries] - - name: container_proc_name - fields: [container.id, proc.name] - comps: [=, in] - values: - - [host, [docker_binaries, k8s_binaries, lxd_binaries, nsenter]] - - name: proc_pname - fields: proc.pname - comps: in - values: [sysdigcloud_binaries, hyperkube, kubelet, protokube, dockerd, tini, aws] - - name: proc_cmdline - fields: [proc.name, proc.cmdline] - comps: [in, contains] - values: - - [[python, python2.7], /opt/draios/bin/sdchecks] - - [[java], sdjagent.jar] - - name: proc_name_parent_name - fields: [proc.name, proc.pname] - comps: [in, in] - values: - - [[loopback], [kubelet]] - - name: proc_name_image_suffix - fields: [proc.name, container.image.repository] - comps: [in, endswith] - values: - - [[agent], "rancher/agent"] - - [[rancher-bridge], "rancher/network-manager"] - - [[calico-node], "calico/node"] - - [[scope], "weaveworks/scope"] output: > Namespace change (setns) by unexpected program (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline parent=%proc.pname %container.info container_id=%container.id image=%container.image.repository:%container.image.tag) @@ -1577,6 +1611,24 @@ - macro: parent_java_running_datastax condition: (proc.pname=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") + +- macro: nginx_running_aws_s3_cp + condition: (proc.pname=nginx and proc.cmdline startswith "sh -c /usr/local/bin/aws s3 cp") + +- macro: consul_running_net_scripts + condition: (proc.pname=consul and (proc.cmdline startswith "sh -c curl" or proc.cmdline startswith "sh -c nc")) + +- macro: consul_running_alert_checks + condition: (proc.pname=consul and proc.cmdline startswith "sh -c /bin/consul-alerts") + +- macro: serf_script + condition: (proc.cmdline startswith "sh -c serf") + +- macro: check_process_status + condition: (proc.cmdline startswith "sh -c kill -0 ") + # In some cases, you may want to consider node processes run directly # in containers as protected shell spawners. Examples include using # pm2-docker or pm2 start some-app.js --no-daemon-mode as the direct @@ -1635,54 +1687,31 @@ and shell_procs and proc.pname exists and protected_shell_spawner + and not proc.pname in (shell_binaries, gitlab_binaries, cron_binaries, user_known_shell_spawn_binaries, + needrestart_binaries, + mesos_shell_binaries, + erl_child_setup, exechealthz, + PM2, PassengerWatchd, c_rehash, svlogd, logrotate, hhvm, serf, + lb-controller, nvidia-installe, runsv, statsite, erlexec, calico-node, + "puma reactor") + and not proc.cmdline in (known_shell_spawn_cmdlines) and not proc.aname in (unicorn_launche) + and not consul_running_net_scripts + and not consul_running_alert_checks + and not nginx_starting_nginx + and not nginx_running_aws_s3_cp and not run_by_package_mgmt_binaries + and not serf_script + and not check_process_status and not run_by_foreman and not python_mesos_marathon_scripting + and not splunk_running_forwarder + and not postgres_running_wal_e and not redis_running_prepost_scripts + and not rabbitmq_running_scripts and not rabbitmqctl_running_scripts and not run_by_appdynamics and not user_shell_container_exclusions - exceptions: - - name: proc_pname - fields: proc.pname - comps: in - values: [shell_binaries, gitlab_binaries, cron_binaries, user_known_shell_spawn_binaries, - needrestart_binaries, - mesos_shell_binaries, - erl_child_setup, exechealthz, - PM2, PassengerWatchd, c_rehash, svlogd, logrotate, hhvm, serf, - lb-controller, nvidia-installe, runsv, statsite, erlexec, calico-node, - "puma reactor"] - - name: cmdlines - fields: proc.cmdline - comps: in - values: [known_shell_spawn_cmdlines] - - name: cmdline_prefix - fields: [proc.cmdline] - comps: [startswith] - values: - - ["sh -c serf"] - - ["sh -c kill -0 "] - - name: pname_cmdline_contains - fields: [proc.pname, proc.cmdline] - comps: [in, contains] - values: - - [[nginx], "/usr/sbin/nginx -c /etc/nginx/nginx.conf"] - - name: pname_cmdline_prefix - fields: [proc.pname, proc.cmdline] - comps: [in, startswith] - values: - - [[consul], "sh -c curl"] - - [[consul], "sh -c nc"] - - [[consul], "sh -c /bin/consul-alerts"] - - [[nginx], "sh -c /usr/local/bin/aws s3 cp"] - - [[splunkd], "sh -c /opt/splunkforwarder"] - - [[postgres], "sh -c envdir /etc/wal-e.d/env /usr/local/bin/wal-e"] - - [[beam.smp], "sh -c exec ps"] - - [[beam.smp], "sh -c exec inet_gethost"] - - [[beam.smp], "sh -s unix:cmd"] - - [[beam.smp], "sh -c exec /bin/sh -s unix:cmd 2>&1"] output: > Shell spawned by untrusted binary (user=%user.name user_loginuid=%user.loginuid shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline pcmdline=%proc.pcmdline gparent=%proc.aname[2] ggparent=%proc.aname[3] @@ -1719,25 +1748,6 @@ container.image.repository endswith /prometheus-node-exporter or container.image.repository endswith /image-inspector)) -# 602401143452.dkr.ecr is official AWS EKS registry. AWS has different ECR repo per region -# 602401143452.dkr.ecr.eu-west-1.amazonaws.com/eks/kube-proxy -# 602401143452.dkr.ecr.us-east-1.amazonaws.com/eks/kube-proxy -# For this reason we use two macro to match all regions -- macro: allowed_aws_eks_registry_root - condition: > - (container.image.repository startswith "602401143452.dkr.ecr") - -- macro: aws_eks_image - condition: > - (allowed_aws_eks_registry_root 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_eks_registry_root and container.image.repository endswith ".amazonaws.com/amazon-k8s-cni") - - # These images are allowed both to run with --privileged and to mount # sensitive paths from the host filesystem. # @@ -1748,6 +1758,27 @@ - list: trusted_images items: [] +# NOTE: This macro is only provided for backwards compatibility with +# older local falco rules files that may have been appending to +# trusted_images. To make customizations, it's better to add containers to +# user_trusted_containers, user_privileged_containers or user_sensitive_mount_containers. +- macro: trusted_containers + condition: (container.image.repository in (trusted_images)) + +# 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, @@ -1783,6 +1814,29 @@ sematext_images ] +- macro: falco_privileged_containers + condition: (openshift_image or + user_trusted_containers 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) + +- list: rancher_images + items: [ + rancher/network-manager, rancher/dns, rancher/agent, + rancher/lb-service-haproxy, rancher/metadata, rancher/healthcheck + ] + # These container images are allowed to mount sensitive paths from the # host filesystem. - list: falco_sensitive_mount_images @@ -1797,6 +1851,12 @@ amazon/amazon-ecs-agent, prom/node-exporter, amazon/cloudwatch-agent ] +- macro: falco_sensitive_mount_containers + condition: (user_trusted_containers or + container.image.repository in (trusted_images) or + container.image.repository in (falco_sensitive_mount_images) or + container.image.repository startswith quay.io/sysdig/) + # These container images are allowed to run with hostnetwork=true - list: falco_hostnetwork_images items: [ @@ -1824,19 +1884,8 @@ condition: > container_started and container and container.privileged=true - and not openshift_image - and not aws_eks_image - exceptions: - - name: image_repo - fields: container.image.repository - comps: in - values: [trusted_images, falco_privileged_images] - - name: image_repo_prefix - fields: [container.image.repository] - comps: [startswith] - values: - - [istio/proxy_] - - [quay.io/sysdig/] + and not falco_privileged_containers + and not user_privileged_containers output: Privileged container started (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag) priority: INFO tags: [container, cis, mitre_privilege_escalation, mitre_lateral_movement] @@ -1879,18 +1928,8 @@ condition: > container_started and container and sensitive_mount + and not falco_sensitive_mount_containers and not user_sensitive_mount_containers - and not aws_eks_image_sensitive_mount - exceptions: - - name: image_repo - fields: container.image.repository - comps: in - values: [trusted_images, falco_sensitive_mount_images] - - name: image_repo_prefix - fields: [container.image.repository] - comps: [startswith] - values: - - [quay.io/sysdig/] output: Container with sensitive mount started (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag mounts=%container.mounts) priority: INFO tags: [container, cis, mitre_lateral_movement] @@ -1911,10 +1950,6 @@ 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 - exceptions: - - name: image_repo - fields: container.image.repository - comps: in output: Container started and not in allowed list (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag) priority: WARNING tags: [container, mitre_lateral_movement] @@ -1930,9 +1965,6 @@ - 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 - exceptions: - - name: user_proc - fields: [user.name, proc.name] output: "System user ran an interactive command (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline container_id=%container.id image=%container.image.repository)" priority: INFO tags: [users, mitre_remote_access_tools] @@ -1949,10 +1981,6 @@ and shell_procs and proc.tty != 0 and container_entrypoint and not user_expected_terminal_shell_in_container_conditions - exceptions: - - name: proc_name_image_suffix - fields: [proc.name, container.image.repository] - comps: [in, endswith] 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 terminal=%proc.tty container_id=%container.id image=%container.image.repository) @@ -2015,6 +2043,9 @@ - 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 @@ -2022,16 +2053,9 @@ 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 - exceptions: - - name: proc_names - fields: proc.name - comps: in - values: [known_system_procs_network_activity_binaries] - - name: proc_proto_sport - fields: [proc.name, fd.l4proto, fd.sport] - values: - - [login, udp, 53] output: > Known system binary sent/received network traffic (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline connection=%fd.name container_id=%container.id image=%container.image.repository) @@ -2070,10 +2094,6 @@ http_proxy_procs and not allowed_ssh_proxy_env and proc.env icontains HTTP_PROXY - exceptions: - - name: proc_names - fields: proc.name - comps: in output: > Program run with disallowed HTTP_PROXY environment variable (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline env=%proc.env parent=%proc.pname container_id=%container.id image=%container.image.repository) @@ -2097,9 +2117,6 @@ condition: > (inbound and consider_interpreted_inbound and interpreted_procs) - exceptions: - - name: proc_proto_sport - fields: [proc.name, fd.l4proto, fd.sport] output: > Interpreted program received/listened for network traffic (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline connection=%fd.name container_id=%container.id image=%container.image.repository) @@ -2111,9 +2128,6 @@ condition: > (outbound and consider_interpreted_outbound and interpreted_procs) - exceptions: - - name: proc_proto_sport - fields: [proc.name, fd.l4proto, fd.sport] output: > Interpreted program performed outgoing network connection (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline connection=%fd.name container_id=%container.id image=%container.image.repository) @@ -2155,15 +2169,34 @@ - rule: Unexpected UDP Traffic desc: UDP traffic not on port 53 (DNS) or other commonly used ports condition: (inbound_outbound) and do_unexpected_udp_check and fd.l4proto=udp and not expected_udp_traffic - exceptions: - - name: proc_proto_sport - fields: [proc.name, fd.l4proto, fd.sport] output: > Unexpected UDP Traffic Seen (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline connection=%fd.name proto=%fd.l4proto evt=%evt.type %evt.args container_id=%container.id image=%container.image.repository) priority: NOTICE tags: [network, mitre_exfiltration] +# 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_themself + 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 @@ -2189,34 +2222,13 @@ evt.type=setuid and evt.dir=> and (known_user_in_container or not container) and not user.name=root + and not somebody_becoming_themself + 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 - exceptions: - - name: proc_names - fields: proc.name - comps: in - values: [known_setuid_binaries, userexec_binaries, mail_binaries, docker_binaries, - nomachine_binaries] - - name: proc_cmdline - fields: [proc.name, proc.cmdline] - comps: [in, contains] - values: - - [[java], sdjagent.jar] - - name: proc_new_uid - fields: [proc.name, evt.arg.uid] - values: - - [nrpe, nagios] - - name: user_new_uid - fields: [user.name, evt.arg.uid] - values: - - [nobody, nobody] - - [www-data, www-data] - - [_apt, _apt] - - [postfix, postfix] - - [pki-agent, pki-agent] - - [pki-acme, pki-acme] - - [nfsnobody, nfsnobody] - - [postgres, postgres] 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 uid=%evt.arg.uid container_id=%container.id image=%container.image.repository) @@ -2237,7 +2249,11 @@ Some innocuous commandlines that don't actually change anything are excluded. condition: > spawned_process and proc.name in (user_mgmt_binaries) and - not container 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 @@ -2245,22 +2261,6 @@ not run_by_google_accounts_daemon and not chage_list and not user_known_user_management_activities - exceptions: - - name: proc_names - fields: proc.name - comps: in - values: [su, sudo, lastlog, nologin, unix_chkpwd] - - name: proc_pnames - fields: proc.pname - comps: in - values: [cron_binaries, systemd, systemd.postins, udev.postinst, run-parts] - - name: cmdline_prefixes - fields: [proc.cmdline] - comps: [startswith] - values: - - ["passwd -S"] - - ["useradd -D"] - - ["systemd --version"] output: > User management binary command run outside of container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline parent=%proc.pname gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4]) @@ -2283,19 +2283,10 @@ condition: > fd.directory = /dev and (evt.type = creat or ((evt.type = open or evt.type = openat) 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 - exceptions: - - name: proc_names - fields: proc.name - comps: in - values: [dev_creation_binaries] - - name: file_names - fields: fd.name - comps: in - values: [allowed_dev_files] - - name: proc_file - fields: [proc.name, fd.name] output: "File created below /dev by untrusted program (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline file=%fd.name container_id=%container.id image=%container.image.repository)" priority: ERROR tags: [filesystem, mitre_persistence] @@ -2318,10 +2309,6 @@ - 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 - exceptions: - - name: proc_name_image_suffix - fields: [proc.name, container.image.repository] - comps: [in, endswith] output: Outbound connection to EC2 instance metadata service (command=%proc.cmdline connection=%fd.name %container.info image=%container.image.repository:%container.image.tag) priority: NOTICE tags: [network, aws, container, mitre_discovery] @@ -2341,15 +2328,10 @@ - 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 consider_metadata_access and not user_known_metadata_access - exceptions: - - name: proc_name_image_suffix - fields: [proc.name, container.image.repository] - comps: [in, endswith] output: Outbound connection to cloud instance metadata service (command=%proc.cmdline connection=%fd.name %container.info image=%container.image.repository:%container.image.tag) priority: NOTICE tags: [network, container, mitre_discovery] - # Containers from IBM Cloud - list: ibm_cloud_containers items: @@ -2366,7 +2348,7 @@ (container.image.repository in (gcr.io/google_containers/hyperkube-amd64, gcr.io/google_containers/kube2sky, docker.io/sysdig/falco, docker.io/sysdig/sysdig, docker.io/falcosecurity/falco, - sysdig/falco, sysdig/sysdig, falcosecurity/falco, + sysdig/falco, sysdig/sysdig, falcosecurity/falco, fluent/fluentd-kubernetes-daemonset, prom/prometheus, ibm_cloud_containers) or (k8s.ns.name = "kube-system")) @@ -2386,10 +2368,6 @@ not k8s_containers and k8s_api_server and not user_known_contact_k8s_api_server_activities - exceptions: - - name: proc_name_image_suffix - fields: [proc.name, container.image.repository] - comps: [in, endswith] output: Unexpected connection to K8s API Server from container (command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag connection=%fd.name) priority: NOTICE tags: [network, k8s, container, mitre_discovery] @@ -2406,10 +2384,6 @@ - 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 - exceptions: - - name: proc_name_image_suffix - fields: [proc.name, container.image.repository] - comps: [in, endswith] output: Unexpected K8s NodePort Connection (command=%proc.cmdline connection=%fd.name container_id=%container.id image=%container.image.repository) priority: NOTICE tags: [network, k8s, container, mitre_port_knocking] @@ -2439,10 +2413,6 @@ and package_mgmt_procs and not package_mgmt_ancestor_procs and not user_known_package_manager_in_container - exceptions: - - name: proc_name_image_suffix - fields: [proc.name, container.image.repository] - comps: [in, endswith] output: > Package management process launched in container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag) @@ -2457,10 +2427,6 @@ (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")) ) - exceptions: - - name: proc_name_image_suffix - fields: [proc.name, container.image.repository] - comps: [in, endswith] output: > Netcat runs inside container that allows remote code execution (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag) @@ -2474,10 +2440,6 @@ desc: Detect network tools launched inside container condition: > spawned_process and container and network_tool_procs and not user_known_network_tool_activities - exceptions: - - name: proc_name_image_suffix - fields: [proc.name, container.image.repository] - comps: [in, endswith] output: > Network tool launched in container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline parent_process=%proc.pname container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag) @@ -2498,9 +2460,6 @@ consider_network_tools_on_host and network_tool_procs and not user_known_network_tool_activities - exceptions: - - name: proc_pname - fields: [proc.name, proc.pname] output: > Network tool launched on host (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline parent_process=%proc.pname) priority: NOTICE @@ -2536,9 +2495,6 @@ ((grep_commands and private_key_or_password) or (proc.name = "find" and (proc.args contains "id_rsa" or proc.args contains "id_dsa"))) ) - exceptions: - - name: proc_pname - fields: [proc.name, proc.pname] output: > Grep private keys or passwords activities found (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline container_id=%container.id container_name=%container.name @@ -2560,25 +2516,20 @@ - macro: allowed_clear_log_files condition: (never_true) +- macro: trusted_logging_images + condition: (container.image.repository endswith "splunk/fluentd-hec" or + container.image.repository endswith "fluent/fluentd-kubernetes-daemonset" or + container.image.repository endswith "openshift3/ose-logging-fluentd" or + container.image.repository endswith "containernetworking/azure-npm") + - rule: Clear Log Activities desc: Detect clearing of critical log files 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 - exceptions: - - name: proc_file_prefix - fields: [proc.name, fd.name] - comps: [in, startswith] - - name: image_suffix - fields: [container.image.repository] - comps: [endswith] - values: - - ["splunk/fluentd-hec"] - - ["fluent/fluentd-kubernetes-daemonset"] - - ["openshift3/ose-logging-fluentd"] - - ["containernetworking/azure-npm"] output: > Log files were tampered (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline file=%fd.name container_id=%container.id image=%container.image.repository) priority: @@ -2597,9 +2548,6 @@ - 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 - exceptions: - - name: proc_pname - fields: [proc.name, proc.pname] output: > Bulk data has been removed from disk (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline file=%fd.name container_id=%container.id image=%container.image.repository) priority: @@ -2637,15 +2585,8 @@ desc: Detect shell history deletion condition: > (modify_shell_history or truncate_shell_history) and - not var_lib_docker_filepath - exceptions: - - name: proc_names - fields: proc.name - comps: in - values: [docker_binaries] - - name: known_shell_history_mods - fields: [proc.name, fd.name] - comps: [=, contains] + 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 fd.name=%fd.name name=%evt.arg.name path=%evt.arg.path oldpath=%evt.arg.oldpath %container.info) priority: @@ -2659,12 +2600,6 @@ 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")) - exceptions: - - name: proc_pname - fields: [proc.name, proc.pname] - - name: known_shell_history_deletes - fields: [proc.name, fd.name] - comps: [=, contains] output: > Shell history had been deleted or renamed (user=%user.name user_loginuid=%user.loginuid type=%evt.type command=%proc.cmdline fd.name=%fd.name name=%evt.arg.name path=%evt.arg.path oldpath=%evt.arg.oldpath %container.info) priority: @@ -2690,13 +2625,9 @@ Detect setuid or setgid bits set via chmod condition: > consider_all_chmods and 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 - exceptions: - - name: proc_names - fields: proc.name - comps: in - values: [user_known_chmod_applications] 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 container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag) @@ -2723,10 +2654,6 @@ consider_hidden_file_creation and not user_known_create_hidden_file_activities and not exe_running_docker_save - exceptions: - - name: proc_file_prefix - fields: [proc.name, fd.name] - comps: [in, startswith] output: > Hidden file or directory created (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline file=%fd.name newpath=%evt.arg.newpath container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag) @@ -2752,9 +2679,6 @@ and container and remote_file_copy_procs and not user_known_remote_file_copy_activities - exceptions: - - name: proc_name_parent_name - fields: [proc.name, proc.pname] output: > Remote file copy tool launched in container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline parent_process=%proc.pname container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag) @@ -2766,10 +2690,6 @@ condition: > create_symlink and (evt.arg.target in (sensitive_file_names) or evt.arg.target in (sensitive_directory_names)) - exceptions: - - name: proc_file_prefix - fields: [proc.name, evt.arg.target] - comps: [in, startswith] output: > Symlinks created over senstivie files (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline target=%evt.arg.target linkpath=%evt.arg.linkpath parent_process=%proc.pname) priority: NOTICE @@ -2866,9 +2786,6 @@ - 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 - exceptions: - - name: proc_sport_sipname - fields: [proc.name, fd.sport, fd.sip.name] enabled: false output: Outbound connection to IP/Port flagged by cryptoioc.ch (command=%proc.cmdline port=%fd.rport ip=%fd.rip container=%container.info image=%container.image.repository) priority: CRITICAL @@ -2877,10 +2794,6 @@ - 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" - exceptions: - - name: proc_pname_parent_cmdline - fields: [proc.pname, proc.cmdline] - comps: [=, contains] output: Possible miner running (command=%proc.cmdline container=%container.info image=%container.image.repository) priority: CRITICAL tags: [process, mitre_execution] @@ -2911,10 +2824,6 @@ - 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) - exceptions: - - name: image_suffix - fields: [container.image.repository] - comps: [endswith] output: "Docker or kubernetes client executed in container (user=%user.name user_loginuid=%user.loginuid %container.info parent=%proc.pname cmdline=%proc.cmdline image=%container.image.repository:%container.image.tag)" priority: WARNING tags: [container, mitre_execution] @@ -2931,10 +2840,6 @@ - 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]=AF_PACKET and consider_packet_socket_communication and container and not proc.name in (user_known_packet_socket_binaries) - exceptions: - - name: proc_name_image_suffix - fields: [proc.name, container.image.repository] - comps: [in, endswith] output: Packet socket was created in a container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline socket_info=%evt.args container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag) priority: NOTICE tags: [network, mitre_discovery] @@ -2943,6 +2848,10 @@ - macro: enabled_rule_network_only_subnet condition: (never_true) +# Images that are allowed to have outbound traffic +- list: images_allow_network_outside_subnet + items: [] + # Namespaces where the rule is enforce - list: namespace_scope_network_only_subnet items: [] @@ -2968,9 +2877,6 @@ container and not network_local_subnet and k8s.ns.name in (namespace_scope_network_only_subnet) - exceptions: - - name: proc_proto_sport - fields: [proc.name, fd.l4proto, fd.sport] output: > Network connection outside local subnet (command=%proc.cmdline connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id @@ -3008,18 +2914,9 @@ allowed_port and inbound_outbound and container and - container.image.repository in (allowed_image) - exceptions: - - name: proc_names - fields: proc.name - comps: in - values: [authorized_server_binaries] - - name: fd_sports - fields: fd.sport - comps: in - values: [authorized_server_port] - - name: proc_proto_sport - fields: [proc.name, fd.l4proto, fd.sport] + container.image.repository in (allowed_image) and + not proc.name in (authorized_server_binary) and + not fd.sport in (authorized_server_port) output: > Network connection outside authorized port and binary (command=%proc.cmdline connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id @@ -3033,10 +2930,6 @@ - rule: Redirect STDOUT/STDIN to Network Connection in Container desc: Detect redirecting stdout/stdin to network connection in container (potential reverse shell). condition: evt.type=dup and evt.dir=> and container and fd.num in (0, 1, 2) and fd.type in ("ipv4", "ipv6") and not user_known_stand_streams_redirect_activities - exceptions: - - name: proc_name_image_suffix - fields: [proc.name, container.image.repository] - comps: [in, endswith] 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 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: WARNING @@ -3060,21 +2953,13 @@ chmod and consider_all_chmods 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")) - exceptions: - - name: proc_name_image_suffix - fields: [proc.name, container.image.repository] - comps: [in, endswith] - - name: cmdline_file - fields: [proc.cmdline, fd.name] - comps: [in, in] - values: - - [["runc:[1:CHILD] init"], [/exec.fifo]] output: Drift detected (chmod), new executable created in a container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode event=%evt.type) priority: ERROR @@ -3087,18 +2972,10 @@ evt.type in (open,openat,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 - exceptions: - - name: proc_name_image_suffix - fields: [proc.name, container.image.repository] - comps: [in, endswith] - - name: cmdline_file - fields: [proc.cmdline, fd.name] - comps: [in, in] - values: - - [["runc:[1:CHILD] init"], [/exec.fifo]] output: Drift detected (open+create), new executable created in a container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode event=%evt.type) priority: ERROR @@ -3108,9 +2985,6 @@ - rule: Outbound Connection to C2 Servers desc: Detect outbound connection to command & control servers condition: outbound and fd.sip in (c2_server_ip_list) - exceptions: - - name: proc_proto_sport - fields: [proc.name, fd.l4proto, fd.sport] output: Outbound connection to C2 server (command=%proc.cmdline connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository) priority: WARNING tags: [network] @@ -3140,9 +3014,9 @@ 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) priority: INFO tags: [container, process] - -#This rule helps detect CVE-2021-3156: -#A privilege escalation to root through heap-based buffer overflow + +# 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 and (proc.args contains -s or proc.args contains -i) and (proc.args contains "\ " or proc.args endswith \)