Falco
Falco consumes events from different sources: system calls, Kubernetes Audit Events, and Cloud Activity Logs (via Falco Plugins, to ingest AWS events from Cloudtrail)
Installation¶
Drivers needed
Falco needs a driver (the kernel module or the eBPF probe) to work; if a prebuilt driver is not available for your distribution/kernel, Falco needs kernel headers installed on the host to build the driver on the fly.
falco-driver-check is a script for checking if Falco drivers are available for your system.
Driver | Description |
---|---|
Kernel Module |
|
eBPF probe |
|
Userspace instrumentation (pdig) |
|
Docker
- There are 2 container images:
- The standard Falco container image, which will try to install the driver on the host
- The no-driver image, which requires the driver already on the host
- Falco requires its kernel module installed directly on the host system
- You can use the standard installation method directly on the host
- Alternatively, you can temporarily use a privileged container to install the driver
# Temporarily use a privileged container to install the driver on the host
$ docker pull falcosecurity/falco-driver-loader:latest
$ docker run --rm -i -t \
--privileged \
-v /root/.falco:/root/.falco \
-v /proc:/host/proc:ro \
-v /boot:/host/boot:ro \
-v /lib/modules:/host/lib/modules:ro \
-v /usr:/host/usr:ro \
-v /etc:/host/etc:ro \
falcosecurity/falco-driver-loader:latest && echo "Falco drivers installed!"
# Run Falco in a container with the principle of least privilege:
$ docker pull falcosecurity/falco-no-driver:latest
$ docker run --rm -d \
--name "falco_daemon" \
--security-opt apparmor:unconfined \
-p 8765:8765 \
-e HOST_ROOT=/ \
--cap-add SYS_PTRACE \
--pid=host $(ls /dev/falco* | xargs -I {} echo --device {}) \
-v /var/run/docker.sock:/var/run/docker.sock \
falcosecurity/falco-no-driver:latest
Kubernetes
- Deployment
- The most secure way to run Falco is to install Falco directly on the host system, so that Falco is isolated from Kubernetes in case of compromise
- Falco can also be run directly in Kubernetes, if isolation is not a concern
$ helm repo add falcosecurity https://falcosecurity.github.io/charts $ helm repo update $ helm install falco \ --create-namespace \ --namespace falco \ --set ebpf.enabled=true \ --set auditLog.enabled=true \ --set falcosidekick.enabled=true \ --set falcosidekick.webui.enabled=true \ falcosecurity/falco
- Verification
- Falco has a webserver that captures K8S events:
# Review the status of the Falco web server # The desired output {"status": "ok"} confirms that the Falco web server is running as expected $ kubectl exec "$container" -- curl -s localhost:8765/healthz; echo
- Check with source of events is configured
$ kubectl logs -n falco -l "app.kubernetes.io/name=falco" -c falco-driver-loader --tail=-1 | grep "* Running falco-driver-loader with" # Output for kernel module * Running falco-driver-loader with: driver=module, compile=yes, download=yes * Running falco-driver-loader with: driver=module, compile=yes, download=yes # Output for eBPF * Running falco-driver-loader with: driver=bpf, compile=yes, download=yes * Running falco-driver-loader with: driver=bpf, compile=yes, download=yes
- Confirm the driver is properly installed:
$ kubectl logs -n falco -l "app.kubernetes.io/name=falco" -c falco-driver-loader --tail=-1 | grep -A 5 "* Success"
- Trigger one of the Falco rules:
$ export POD_NAME=$(kubectl get pods --namespace falco -l "app.kubernetes.io/name=falco" -o jsonpath="{.items[0].metadata.name}") $ kubectl -n falco exec ${POD_NAME} -- find /root -name "id_rsa" # Check that Falco correctly intercepted the potentially dangerous command: $ kubectl logs -n falco -l "app.kubernetes.io/name=falco" | grep Warning
- Falco has a webserver that captures K8S events:
Additional setup for self-hosted Kubernetes
Configure the K8s audit policy:
- Download the policy
$ wget https://raw.githubusercontent.com/falcosecurity/evolution/master/examples/k8s_audit_config/audit-policy.yaml
- Define and deploy the webhook audit backend
# This manifest defines how to send audit events to a remote web API # (in this case, the Falco service ingesting the K8s audit logs) $ export IP=$(kubectl get service --namespace falco falco -o=jsonpath={.spec.clusterIP}) $ cat << EOF | sudo tee webhook-config.yaml apiVersion: v1 kind: Config clusters: - name: falco cluster: server: http://$IP:8765/k8s-audit contexts: - context: cluster: falco user: "" name: default-context current-context: default-context preferences: {} users: [] EOF
- Patch the kube-apiserver using the flags
audit-log-path
,audit-policy-file
, andaudit-webhook-config-file
Falco Rules¶
Rule files
- Default rules file:
/etc/falco/falco_rules.yaml
- Not to be modified
- Contains a predefined set of rules designed to provide good coverage in a variety of situations
- Show the name and description of all rules:
kubectl exec ${FALCO_POD} -n falco -- falco -L
- Local rules file:
/etc/falco/falco_rules.local.yaml
- For additions/overrides/modifications
Main Constructs¶
A Falco rules file is a YAML file containing three types of elements:
Element | Description | Fields |
---|---|---|
rule |
A condition under which an alert should be generated, and the output string to send with the alert |
|
macro |
A rule condition snippet that can be re-used inside rules and other macros |
|
list |
Named collections of items that can be included in rules, macros, or other lists |
|
- rule: shell_in_container
desc: notice shell activity within a container
condition: container.id != host and proc.name = bash
output: shell in a container (user=%user.name container_name=%container.name)
priority: warning
tags: [shell, container]
- macro: in_container
condition: container.id != host
- macro: spawned_shell
condition: proc.name = bash
- rule: shell_in_container
desc: notice shell activity within a container
condition: spawned_shell and in_container
output: shell in a container (user=%user.name ...)
priority: WARNING
- list: shell_binaries
items: [bash, csh, ksh, sh, tcsh, zsh, dash]
- list: userexec_binaries
items: [sudo, su]
- list: known_binaries
items: [shell_binaries, userexec_binaries]
- macro: safe_procs
condition: proc.name in (known_binaries)
Field Classes¶
- Description
-
- Falco events expose many different fields, organized in field classes
- Falco enriches events with metadata from the available contexts. Not all field classes or fields are available for all the events
Field Class | Description |
---|---|
evt |
|
process |
Additional information about the process and thread executing the syscall event |
user |
Information about the user executing the specific event |
fd |
Every syscall that has a file descriptor in its arguments has these fields set with information related to the file |
container |
|
k8s |
Kubernetes related context |
Manipulation¶
Action | Description |
---|---|
Appending |
|
Override macros |
|
Enable/Disable default rules |
|
# There is a rule in falco_rules.yaml
- list: sensitive_directory_names
items: [/, /etc, /etc/, /root, /root/]
# Add the following list definition to the my_rules.yaml file
- list: sensitive_directory_names
append: true
items: [/mnt]
# Original macro in falco_rules.yaml:
- macro: user_trusted_containers
condition: (never_true)
# Overriding macro in falco_rules.local.yaml:
- macro: user_trusted_containers
condition: (container.image startswith sysdig/agent)
- Enable via existing macro:
# Disable the default rule "Packet socket created in container" - macro: consider_packet_socket_communication condition: (always_true)
- Enable via custom rule definitions:
- rule: User mgmt binaries append: true condition: and (never_true)
Exceptions¶
There are multiple ways to deal with noisy alerts:
Method | Description |
---|---|
Disabling one or more default rules (not recommended) | Disabling the entire rule reduces the detection scope of Falco |
Modifying a default rule condition | Concatenate one or more conditions to the default rule to exclude a particular process, file descriptor or any other pair of field-value that identifies the exception |
Defining rule exceptions | If a particular rule requires tuning, an exception can be defined |
- rule: <the_name_of_the_rule>
desc: (...)
condition: (...)
output: (...)
tags: (...)
exceptions:
- name: <name_of_the_exception>
fields: [proc.name, fd.name]
comps: [=, in]
values:
- [my_bin_A, [my_file_A]]
- [custom_bin_B, [allowed_file_for_B, other_B_file]]
Exception that removes alerts for the Run shell untrusted rule when:
proc.pname = apache2
proc.cmdline = bash -c ls /root > /tmp/pmt
customRules:
custom_rules_from_default: |-
(...)
- rule: Run shell untrusted
(...)
exceptions:
- name: app1_shell_runner
fields: [proc.pname, proc.cmdline]
comps: [=, =]
values:
- [apache2, bash -c ls /root > /tmp/pmt]
(...)
Tip
- Fields, comps and values are grouped in tuples
- They are joined/matched following the order in which they are defined.
- Example:
- The exception below considers
proc.name = process_A
andfd.name in file_A
- The first field and the first value are compared using the first operator
- The second field, with the second operator and value/values
- The exception below considers
- rule:
(...)
exceptions:
- name: example_exception
fields: [proc.name, fd.name]
comps: [=, in]
values:
- [process_A, file_A]
- [process_B, [file_B, file_C]]
Falco Alerts¶
- When a Falco Rule is violated, an alert is triggered
- Alerts can be sent to multiple supported channels
Channel | Description |
---|---|
Standard Output |
|
File Output |
|
Program output |
|
HTTP endpoint |
|
gRPC client |
|
Falco Response Engine¶
Falco is a Detection Engine, but it can be upgraded to a Response Engine with the help of Falco Sidekick.
Component | Description | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
falcosidekick | ![]()
|
|||||||||
sample-event-generator |
|
|||||||||
falco-exporter |
|
Resources¶
General¶
Link | Description |
---|---|
Sysdig Official Docs | |
Sysdig Falco 101 | All you need to learn to get started with Falco |
Sysdig Falco Hands-on Labs | Learn and practice with Falco in your Browser |
Sysdig Getting started with runtime security and Falco | How to get started with Falco |
Analyze Kubernetes Audit logs using Falco | Detect intrusions that happened in your Kubernetes cluster through audit logs using Falco |
Rulesets¶
Link | Description |
---|---|
Using Falco to monitor outbound traffic for Pods in Kubernetes | Walkthrough on how to use Falco to monitor the network traffic of your Pods |