Skip to main content

Falco Runtime Security

Falco is an important behavioral analysis tool for the CKS exam.

It's important to understand:

  • How to install directly on the host
  • How to check Falco log events
  • How to override a default rule to change the output, since creating a rule is complex

Check out more about Falco

The host installation is simple.

This installation should be done on all hosts.

curl -fsSL https://falco.org/repo/falcosecurity-packages.asc | \
sudo gpg --dearmor -o /usr/share/keyrings/falco-archive-keyring.gpg

sudo bash -c 'cat << EOF > /etc/apt/sources.list.d/falcosecurity.list
deb [signed-by=/usr/share/keyrings/falco-archive-keyring.gpg] https://download.falco.org/packages/deb stable main
EOF'

sudo apt-get update -y

sudo apt-get install -y falco

# There are several services, but it will detect the machine's driver and launch the correct service
systemctl status falco-modern-bpf.service

Run any container and enter the bash of this container.

root@cks-master:~# k run pod --image=httpd -oyaml --dry-run=client > malicious.yaml
root@cks-master:~# vim malicious.yaml
root@cks-master:~# cat malicious.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod
name: pod
spec:
containers:
- image: httpd
name: pod
resources: {}
env:
- name: SECRET
value: "asdf1234"
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}

root@cks-master:~# k apply -f malicious.yaml
pod/pod created

Now let's check which host this pod is running on and get the logs.

# Let's check where this pod is running
# Worker node
root@cks-master:~# k get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod 1/1 Running 0 99s 192.168.1.38 cks-worker <none> <none>

# Accessing the shell of this pod to generate an alert
root@cks-master:~# k exec -it pod -- bash
root@pod:/usr/local/apache2# exit
exit

To get the logs we can check syslog.

root@cks-worker:~# cat /var/log/syslog | grep Notice
Sep 10 13:54:44 cks-worker falco: 13:54:44.394900248: Notice A shell was spawned in a container with an attached terminal (evt_type=execve user=root user_uid=0 user_loginuid=-1 process=bash proc_exepath=/usr/bin/bash parent=runc command=bash terminal=34816 exe_flags=EXE_WRITABLE container_id=7c8973f32410 container_name=pod)

Falco has all files in /etc/falco

root@cks-worker:~# ls /etc/falco
config.d falco.yaml falco_rules.local.yaml falco_rules.yaml rules.d

The rule below is the one that was violated. It's a default rule and is in falco_rules.yaml. Let's search for this output in that file.

root@cks-worker:/etc/falco# cat falco_rules.yaml | grep "A shell was spawned in a container with an attached terminal" -B20 -A10

# In some cases, a shell is expected to be run in a container. For example, configuration
# management software may do this, which is expected.
- macro: user_expected_terminal_shell_in_container_conditions
condition: (never_true)

######################## This block ############################
- rule: Terminal shell in container
desc: >
A shell was used as the entrypoint/exec point into a container with an attached terminal. Parent process may have
legitimately already exited and be null (read container_entrypoint macro). Common when using "kubectl exec" in Kubernetes.
Correlate with k8saudit exec logs if possible to find user or serviceaccount token used (fuzzy correlation by namespace and pod name).
Rather than considering it a standalone rule, it may be best used as generic auditing rule while examining other triggered
rules in this container/tty.
condition: >
spawned_process
and container
and shell_procs
and proc.tty != 0
and container_entrypoint
and not user_expected_terminal_shell_in_container_conditions
output: A shell was spawned in a container with an attached terminal (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
priority: NOTICE
tags: [maturity_stable, container, shell, mitre_execution, T1059]
#####################################################################
# For some container types (mesos), there isn't a container image to
# work with, and the container name is autogenerated, so there isn't
# any stable aspect of the software to work with. In this case, we
# fall back to allowing certain command lines.
- list: known_shell_spawn_cmdlines
items: [
'"sh -c uname -p 2> /dev/null"',\

To override this rule we can copy it and place it in the falco_rules.local.yaml file. This file is loaded after falco_rules.yaml, overriding the rule.

Let's change the output to TIME, USERNAME, CONTAINER_NAME, CONTAINER_ID and the priority to WARNING.

root@cks-worker:~# cd /etc/falco
root@cks-worker:/etc/falco# vim falco_rules.local.yaml
root@cks-worker:/etc/falco# cat falco_rules.local.yaml
- rule: Terminal shell in container
desc: >
A shell was used as the entrypoint/exec point into a container with an attached terminal. Parent process may have
legitimately already exited and be null (read container_entrypoint macro). Common when using "kubectl exec" in Kubernetes.
Correlate with k8saudit exec logs if possible to find user or serviceaccount token used (fuzzy correlation by namespace and pod name).
Rather than considering it a standalone rule, it may be best used as generic auditing rule while examining other triggered
rules in this container/tty.
condition: >
spawned_process
and container
and shell_procs
and proc.tty != 0
and container_entrypoint
and not user_expected_terminal_shell_in_container_conditions
# Changed the output
output: >
%evt.time,user=%user.name,%container.name,%container.id
# Changed the priority
priority: WARNING
tags: [maturity_stable, container, shell, mitre_execution, T1059]# Your custom rules!

# Restart the service to pick up the new rules
root@cks-worker:/etc/falco# systemctl restart falco-bpf.service falco-modern-bpf.service

# Enter the shell the same way we did before and then check syslog

root@cks-worker:/etc/falco# cat /var/log/syslog | grep Warning
Sep 9 09:41:15 cks-worker kernel: [ 1.404901] i8042: Warning: Keylock active
Sep 10 14:08:38 cks-worker falco: 14:08:38.224023753: Warning 14:08:38.224023753,user=root,pod,7c8973f32410
Sep 10 14:08:38 cks-worker falco: 14:08:38.224050871: Warning 14:08:38.224050871,user=root,pod,7c8973f32410

Depending on what is requested, we can filter events using the fields defined in supported-fields.