Add additional shell spawning command lines.
Allow package management binaries in containers--lots of people seem to
do it. Also allow pycompile/py3compile.
I need to refactor the shell spawners to more clearly isolate shell
spawners that we don't want to occur in a container from ones that can
run both inside and outside of a container.
These changes allow for a local rules file that will be preserved across
upgrades and allows the main rules file to be overwritten across upgrades.
- Move all config/rules files below /etc/falco/
- Add a "local rules" file /etc/falco/falco_rules.local.yaml. The intent
is that it contains modifications/deltas to the main rules file
/etc/falco/falco_rules.yaml. The main falco_rules.yaml should be
treated as immutable.
- All config files are flagged so they are not overwritten on upgrade.
- Change the handling of the config item "rules_file" in falco.yaml to
allow a list of files. By default, this list contains:
[/etc/falco/falco_rules.yaml, /etc/falco/falco_rules.local.yaml].
Also change rpm/debian packaging to ensure that the above files are
preserved across upgrades:
- Use relative paths for share/bin dirs. This ensures that when packaged
as rpms they won't be flagged as config files.
- Add CMAKE_INSTALL_PREFIX to FALCO_ENGINE_LUA_DIR now that it's relative.
- In debian packaging, flag
/etc/falco/{falco.yaml,falco_rules.yaml,falco_rules.local.yaml} as
conffiles. That way they are preserved across upgrades if modified.
- In rpm packaging when using cmake, any files installed with an
absolute path are automatically flagged as %config. The only files
directly installed are now the config files, so that addresses the problem.
Add CMAKE_INSTALL_PREFIX to lua dir.
* Updates from beta customers.
- add anacron as a cron program
* Reorganize package management binaries
Split package_management_binaries into two separate lists rpm_binaries
and deb_binaries. unattended-upgr is common to both worlds so it's still
in package_management_binaries.
Also change Write below rpm database to use rpm_binaries instead of its
own list.
Also add 75-system-updat (truncated) as a shell spawner.
* Add rules for jenkins
Add rules that allow jenkins to spawn shells, both in containers and
directly on the host.
Also handle jenkins slaves that run /tmp/slave.jar.
* Allow npm to run shells.
Not yet allowing node to run shells itself, although we want to add
something to reduce node-related FPs.
* Allow urlgrabber/git-remote to access /etc
urlgrabber and git-remote both try to access the RHEL nss database,
containing shared certificates. I may change this in a more general way
by changing open_read/open_write to only look for successful opens.
* Only look for successful open_read/open_writes
Change the macros open_read/open_write to only trigger on successful
opens (when fd.num > 0). This is a pretty big change to behavior, but
is more intuitive.
This required a small update to the open counts for a couple of unit
tests, but otherwise they still all passed with this change.
* Allow rename_device to write below /dev
Part of udev.
* Allow cloud-init to spawn shells.
Part of https://cloud-init.io/
* Allow python to run a shell that runs sdchecks
sdchecks is a part of the sysdig monitor agent.
* Allow dev creation binaries to write below etc.
Specifically this includes blkid and /etc/blkid/blkid.tab.
* Allow git binaries to spawn shells.
They were already allowed to run shells in a container.
* Add /dev/kmsg as an allowed /dev file
Allows userspace programs to write to kernel log.
* Allow other make programs to spawn shells.
Also allow gmake/cmake to spawn shells and put them in their own list
make_binaries.
* Add better mesos support.
Mesos slaves appear to be in a container due to their cgroup and can run
programs mesos-health-check/mesos-docker-exec to monitor the containers
on the slave, so allow them to run shells.
Add mesos-agent, mesos-logrotate, mesos-fetch as shell spawners both in
and out of containers.
Add gen_resolvconf. (short for gen_resolvconf.py) as a program that can
write to /etc.
Add toybox (used by mesos, part of http://landley.net/toybox/about.html)
as a shell spawner.
* systemd can listen on network ports.
Systemd can listen on network ports to launch daemons on demand, so
allow it to perform network activity.
* Let docker binaries setuid.
Let docker binaries setuid and add docker-entrypoi (truncation
intentional) to the set of docker binaries.
* Change cis-related rules to be less noisy
Change the two cis-related falco rules "File Open by Privileged
Container" and "Sensitive Mount by Container" to be less noisy. We found
in practice that tracking every open still results in too many falco
notifications.
For now, change the rules to only track the initial process start in the
container by looking for vpid=1. This should result in only triggering
when a privileged/sensitive mount container is started. This is slightly
less coverage but is far less noisy.
* Add quay.io/sysdig as trusted containers
These are used for sysdig cloud onpremise deployments.
* Add gitlab-runner-b(uild) as a gitlab binary.
Add gitlab-runner-b (truncated gitlab-runner-build) as a gitlab binary.
* Add ceph as a shell spawner.
Also allow ceph to spawn shells in a container.
* Allow some shells by command line.
For some mesos containers, where the container doesn't have an image and
is just a tarball in a cgroup/namespace, we don't have any image to work
with. In those cases, allow specific command lines.
* Allow user 'nobody' to setuid.
Allow the user nobody to setuid. This depends on the user nobody being
set up in the first place to have no access, but that should be an ok
assumption.
* Additional allowed shell commandlines
* Add additional shells.
* Allow multiple users to become themself.
Add rule somebody_becoming_themself that handles cases of nobody and
www-data trying to setuid to themself. The sysdig filter language
doesn't support template/variable values to allow "user.name=X and
evt.arg.uid=X for a given X", so we have to enumerate the users.
* More known spawn command lines
* Let make binaries be run in containers.
Some CI/CD pipelines build in containers.
* Add additional shell spawning command lines
* Add additional apt program apt-listchanges.
* Add gitlab-ce as shell spawning container.
* Allow PM2 to spawn shells in containers.
Was already in the general list, seen in some customers, so adding to
the in containers list.
* Clean up pass to fix long lines.
Take a pass through the rules making sure each line is < 120 characters.
* Change tests for privileged container rules.
Change unit tests to reflect the new privileged/sensitive mount
container rules that only detect container launch.
Review the priorities used by each rule and try to use a consistent set
that uses more of the possible priorities. The general guidelines I used
were:
- If a rule is related to a write of state (i.e. filesystem, etc.),
its priority is ERROR.
- If a rule is related to an unauthorized read of state (i.e. reading
sensitive filees, etc.), its priority is WARNING.
- If a rule is related to unexpected behavior (spawning an unexpected
shell in a container, opening an unexpected network connection, etc.), its priority
is NOTICE.
- If a rule is related to behaving against good practices (unexpected
privileged containers, containers with sensitive mounts, running
interactive commands as root), its priority is INFO.
One exception is that the most FP-prone rule (Run shell untrusted) has a
priority of DEBUG.
Allow the sysdig cloud agent to call setns to collect java process
metrics.
We've also seen cases where some of the intermediate processes created
below runc appear to call setns. It appears that this only should happen
if some events (like the execve that spawns the intermediate processes)
are lost, but just to be safe allow processes starting with "runc:" to
call setns.
Add a new falco rule "Terminal shell in container" that looks for shells
spawned in a container with an attached terminal. This is similar to the
existing "Run shell in container" rule, but doesn't have as many
exceptions as we expect this to be even less rare.
- Sometimes systemd changes its process name to '(systemd)', probably
for a forked daemon process. Add that version to login_binaries.
- Add sv (part of runit) as a program that can write below /etc.
- Allow all /dev/tty* files by moving /dev/tty from the list to a
"startswith /dev/tty" condition.
Tag the existing ruleset to group tags in a meaningful way. The added
tags are:
- filesystem: the rule relates to reading/writing files
- sofware_mgmt: the rule relates to any software/package management
tool like rpm, dpkg, etc.
- process: the rule relates to starting a new process or changing the
state of a current process.
- database: the rule relates to databases
- host: the rule *only* works outside of containers
- shell: the rule specifically relates to starting shells
- container: the rule *only* works inside containers
- cis: the rule is related to the CIS Docker benchmark.
- users: the rule relates to management of users or changing the
identity of a running process.
- network: the rule relates to network activity
Rules can have multiple tags if they relate to multiple of the
above. Rules do not have to have tags, although all the current rules do.
- Add flanneld as a privileged container.
- Add parentheses grouping around many of the "x running y"
containers. I haven't found this strictly necessary with their
current use in rules, but this ensures they will be isolated when
used.
- Allow denyhosts to spawn shells--it runs iptables to add/remove hosts
from its deny list.
This is a rework of a PR made by @juju4 that had a bunch of additions
related to running other security/monitoring products, including aide,
bro, icinga2, nagios, ansible, etc.
This overlapped a lot with changes I had been making to reduce
noisiness, so rather than have @juju4 deal with the conflicts I took the
changes and made a separate commit with the non-conflicting additions.
A summary of the changes:
- Add docker-compose as a docker binary.
- Add showq/critical-stack as setuid binaries.
- Add lxd binaries
- Add some additional package management binaries.
- Add support for host intrustion detection systems like aide.
- Add support for network intrustion detections systems like bro.
- Add support for monitoring systems like nagios, icinga2, npcd.
- Other one-off additions to other lists of mail/etc programs.
A new trace file falco-event-generator.scap contains the result of
running the falco event generator in docker, via:
docker run --security-opt seccomp=unconfined sysdig/falco-event-generator:latest /usr/local/bin/event_generator --once
Make sure this trace file detects the exact set of events we expect for
each rule. This required adding a new verification method
check_detections_by_rule that finds the per-rule counts and compares
them to the expected counts, which are included in the test description
under the key "detect_counts".
This is the first time a trace file for a test is actually in one of the
downloaded zip files. This means it will be tested twice (one for simple
detect-or-not, once for actual counts).
Adding this test showed a problem with Run shell in container
rule--since sysdig/falco-event-generator startswith sysdig/falco, it was
being treated as a trusted container. Modify the macro
trusted_containers to not allow falco-event-generator to be trusted.
- Add a second possible location for denyhosts
- Add PM2 (http://pm2.keymetrics.io/) as a shell spawner.
- There was a bug in use of ansible_running_python. We actually need
two variants depending on whether ansible is the parent or current
process. parent_ansble_running_python is used for Run shell
untrusted, ansible_running_python is used for other rules.
We had added this image while the changes in
https://github.com/draios/falco/pull/177 made it to everyone. This is in
a release now, so we'll remove it from the rule set.
Several changes to reduce spurious alerts when managing machines via
ansible:
- Add ansible_running_python (that is, ansible-spawned python scripts)
as scripts that can read sensitive files and write below
/etc. Notably this is the user ansible module.
- Also add comments to ansible_running_python suggesting users make it
more strict by specifically naming the root directory for ansible
scripts.
- Add pypy as a python variant that can run ansible-related scripts.
Also other changes to reduce FPs:
- add apt-add-reposit, apt-auto-remova (truncation intentional),
apt-get, apt, apt-key as package management programs, and add package
management binaries to the set of shell spawners. The overlapping
binaries that were in known_shell_spawn_binaries were removed.
- add passwd_binaries, gpg, insserv, apparmor_parser, update-mime,
tzdata.{config,postinst}, systemd-machine, and debconf-show to
the set of binaries that can write below /etc.
- Add vsftpd as a program that can read sensitive files.
- Add additional programs (incl. python support programs like pip,
pycompile) as ones that can spawn shells.
- Allow privileged containers to spawn shells.
- Break out the set of files below /dev that are written to with O_CREAT
into a separate list, and add /dev/random,urandom,console to the list.
- Add python running denyhosts as a program that can write below /etc.
- Also add binaries starting with linux-image- as ones that can spawn
shells. These are perl scripts run as a part of installing
linux-image-N.N packages.
Changes to allow shells spawned by ansible. In general this is actually
pretty difficult--on the remote managed machine, ansible performs
actions simply by running python over ssh without any explicit ansible
helper or command line.
One (weak) hint is that the python scripts being run are usually under a
directory with ansible in the name. So use that as the basis for a macro
ansible_running_python. In turn, that macro is used as a negative
condition for the run shell untrusted rule.
This is a pretty fragile and easily exploited condition, so add a note
to the macro saying so.
Feedback from a falco user:
--
to more findings from last night:
logrotate cronjob (Debian default):
Shell spawned by untrusted binary (user=root shell=sh parent=logrotate cmdline=sh -c invoke-rc.d rsyslog rotate > /dev/null logrotate_script /var/log/syslog)
passwd cronjob (Debian default):
Sensitive file opened for reading by non-trusted program (user=root name=cmp command=cmp -s shadow.bak /etc/shadow file=/etc/shadow)
--
New macro cmp_cp_by_passwd allows cmp/cp to be run by passwd to examine
sensitive files. Add logrotate as a program that can spawn a shell.
Also do some cleanups, moving items to lists and splitting long
single-line conditions into multiple lines.
Add cchh/sysdig as a trusted container. We'll probably remove this once
the next agent release occurs that has the fix
https://github.com/draios/falco/pull/177.
Also reformat to avoid long lines.
Periodically both apt and apt-get will spawn shells to update success timestamps and motd.
falco-CLA-1.0-signed-off-by: Jonathan Coetzee <jon@thancoetzee.com>
SSH'ing into an Ubuntu 16.04 box triggers a bunch of "Sensitive file opened for reading by non-trusted program" errors caused by systemd
falco-CLA-1.0-signed-off-by: Jonathan Coetzee jon@thancoetzee.com