Skip to main content

Falco Runtime Security

Falco es una herramienta de análisis comportamental importante para el CKS.

Es importante entender:

  • Cómo instalar directamente en el host.
  • Cómo verificar los eventos de logs del Falco.
  • Hacer el sobrescritura de una regla predeterminada para cambiar el output una vez que la creación de una regla es compleja.

Consulta sobre Falco

La instalación en el host es simple.

Esta instalación debe hacerse en todos los 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

# Existen varios servicios, pero él detectará cuál es el driver de la máquina y lanzará el servicio correcto.
systemctl status falco-modern-bpf.service

Ejecuta un contenedor cualquiera y entra al bash de este contenedor.


```bash
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

Ahora vamos a verificar en qué host está corriendo este pod y obtener los logs.

# Vamos a verificar dónde está corriendo este pod
# Node worker
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>

# Accediendo al shell de este pod para generar una alerta
root@cks-master:~# k exec -it pod -- bash
root@pod:/usr/local/apache2# exit
exit

Para obtener los logs podemos verificar en el 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 posee todos los archivos en /etc/falco

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

La regla abajo es la que fue violada. Es una regla predeterminada y está en falco_rules.yaml. Vamos a buscar por esta salida en ese archivo.

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)

######################## Este bloque ############################
- 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"',\

Para hacer una sobrescritura de esta regla podemos copiar y colocar en el archivo falco_rules.local.yaml. Este archivo es cargado después del falco_rules.yaml sobrescribiendo la regla.

Vamos a cambiar el output para TIME,USERNAME,CONTAINER_NAME,CONTAINER_ID y la prioridad para 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
# Cambiamos el output
output: >
%evt.time,user=%user.name,%container.name,%container.id
# Cambiamos la prioridad
priority: WARNING
tags: [maturity_stable, container, shell, mitre_execution, T1059]# Your custom rules!

# Reinicia el servicio para obtener las nuevas reglas.
root@cks-worker:/etc/falco# systemctl restart falco-bpf.service falco-modern-bpf.service

# Entra en el shell de la forma como hicimos anteriormente y después verifica el 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

Dependiendo de lo que se pida podemos filtrar los eventos usando los campos definidos en supported-fields.