Skip to main content

Pregunta 2 | Seguridad en Tiempo de Ejecución con Falco

Usar contexto: kubectl config use-context workload-prod

Falco está instalado con la configuración predeterminada en el nodo cluster1-node1. Conecta usando ssh cluster1-node1. Úsalo para:

Encontrar un Pod ejecutando la imagen nginx que crea procesos de gestión de paquetes no deseados dentro de su contenedor.

Encontrar un Pod ejecutando la imagen httpd que modifica /etc/passwd.

Guarda los logs de Falco para el caso 1 en /opt/course/2/falco.log en el formato:

tiempo-con-nanosegundos,id-contenedor,nombre-contenedor,nombre-usuario

No debe haber ninguna otra información en ninguna línea. Recopila los logs durante al menos 30 segundos.

Después, elimina las amenazas (tanto 1 como 2) escalando las réplicas de los Deployments que controlan los Pods infractores a 0.


Respuesta:

Falco, el proyecto de seguridad en tiempo de ejecución nativo de la nube de código abierto, es el motor de detección de amenazas de facto para Kubernetes.

NOTA: Otras herramientas con las que podrías tener que familiarizarte son sysdig o tracee

Usar Falco como servicio

Primero podemos investigar un poco la configuración de Falco:

ssh cluster1-node1

➜ root@cluster1-node1:~# service falco status
● falco.service - LSB: Falco syscall activity monitoring agent
Loaded: loaded (/etc/init.d/falco; generated)
Active: active (running) since Sat 2020-10-10 06:36:15 UTC; 2h 1min ago
...

➜ root@cluster1-node1:~# cd /etc/falco

➜ root@cluster1-node1:/etc/falco# ls
falco.yaml falco_rules.local.yaml falco_rules.yaml k8s_audit_rules.yaml rules.available rules.d

Esta es la configuración predeterminada, si miramos en falco.yaml podemos ver:

# /etc/falco/falco.yaml

...
# Dónde deben ir las notificaciones de seguridad.
# Se pueden habilitar múltiples salidas.

syslog_output:
enabled: true
...

Esto significa que Falco está escribiendo en syslog, por lo tanto podemos hacer:

➜ root@cluster1-node1:~# cat /var/log/syslog | grep falco
Sep 15 08:44:04 ubuntu2004 falco: Falco version 0.29.1 (driver version 17f5df52a7d9ed6bb12d3b1768460def8439936d)
Sep 15 08:44:04 ubuntu2004 falco: Falco initialized with configuration file /etc/falco/falco.yaml
Sep 15 08:44:04 ubuntu2004 falco: Loading rules from file /etc/falco/falco_rules.yaml:
...

Sí, bastante actividad allí. Investiguemos el primer Pod infractor:

➜ root@cluster1-node1:~# cat /var/log/syslog | grep falco | grep nginx | grep process
Sep 16 06:23:47 ubuntu2004 falco: 06:23:47.376241377: Error Package management process launched in container (user=root user_loginuid=-1 command=apk container_id=7a5ea6a080d1 container_name=nginx image=docker.io/library/nginx:1.19.2-alpine)
...

➜ root@cluster1-node1:~# crictl ps -id 7a5ea6a080d1
CONTAINER ID IMAGE NAME ... POD ID
7a5ea6a080d1b 6f715d38cfe0e nginx ... 7a864406b9794

root@cluster1-node1:~# crictl pods -id 7a864406b9794
POD ID ... NAME NAMESPACE ...
7a864406b9794 ... webapi-6cfddcd6f4-ftxg4 team-blue ...

El primer Pod es webapi-6cfddcd6f4-ftxg4 en el Namespace team-blue.

➜ root@cluster1-node1:~# cat /var/log/syslog | grep falco | grep httpd | grep passwd
Sep 16 06:23:48 ubuntu2004 falco: 06:23:48.830962378: Error File below /etc opened for writing (user=root user_loginuid=-1 command=sed -i $d /etc/passwd parent=sh pcmdline=sh -c echo hacker >> /etc/passwd; sed -i '$d' /etc/passwd; true file=/etc/passwdngFmAl program=sed gparent=<NA> ggparent=<NA> gggparent=<NA> container_id=b1339d5cc2de image=docker.io/library/httpd)

➜ root@cluster1-node1:~# crictl ps -id b1339d5cc2de
CONTAINER ID IMAGE NAME ... POD ID
b1339d5cc2dee f6b40f9f8ad71 httpd ... 595af943c3245

root@cluster1-node1:~# crictl pods -id 595af943c3245
POD ID ... NAME NAMESPACE ...
595af943c3245 ... rating-service-68cbdf7b7-v2p6g team-purple ...

El segundo Pod es rating-service-68cbdf7b7-v2p6g en el Namespace team-purple.

Eliminar Pods infractores

Los logs anteriores deberían permitirnos encontrar y "eliminar" los Pods infractores:

➜ k get pod -A | grep webapi
team-blue webapi-6cfddcd6f4-ftxg4 1/1 Running

➜ k -n team-blue scale deploy webapi --replicas 0
deployment.apps/webapi scaled

➜ k get pod -A | grep rating-service
team-purple rating-service-68cbdf7b7-v2p6g 1/1 Running

➜ k -n team-purple scale deploy rating-service --replicas 0
deployment.apps/rating-service scaled

Usar Falco desde la línea de comandos

También podemos usar Falco directamente desde la línea de comandos, pero solo si el servicio está deshabilitado:

➜ root@cluster1-node1:~# service falco stop

➜ root@cluster1-node1:~# falco
Thu Sep 16 06:33:11 2021: Falco version 0.29.1 (driver version 17f5df52a7d9ed6bb12d3b1768460def8439936d)
Thu Sep 16 06:33:11 2021: Falco initialized with configuration file /etc/falco/falco.yaml
Thu Sep 16 06:33:11 2021: Loading rules from file /etc/falco/falco_rules.yaml:
Thu Sep 16 06:33:11 2021: Loading rules from file /etc/falco/falco_rules.local.yaml:
Thu Sep 16 06:33:11 2021: Loading rules from file /etc/falco/k8s_audit_rules.yaml:
Thu Sep 16 06:33:12 2021: Starting internal webserver, listening on port 8765
06:33:17.382603204: Error Package management process launched in container (user=root user_loginuid=-1 command=apk container_id=7a5ea6a080d1 container_name=nginx image=docker.io/library/nginx:1.19.2-alpine)
...

Podemos ver que se cargan los archivos de reglas y luego se imprimen los logs.

Crear logs en el formato correcto

La tarea requiere que almacenemos logs para "procesos de gestión de paquetes no deseados" en el formato tiempo,id-contenedor,nombre-contenedor,nombre-usuario. La salida de falco muestra entradas para "Error Package management process launched" en un formato predeterminado. Encontremos el archivo apropiado que contiene la regla y modifiquémosla:

➜ root@cluster1-node1:~# cd /etc/falco/

➜ root@cluster1-node1:/etc/falco# grep -r "Package management process launched" .
./falco_rules.yaml: Package management process launched in container (user=%user.name user_loginuid=%user.loginuid

➜ root@cluster1-node1:/etc/falco# cp falco_rules.yaml falco_rules.yaml_ori

➜ root@cluster1-node1:/etc/falco# vim falco_rules.yaml

Encuentra la regla que se ve así:

# El contenedor se supone que es inmutable. La gestión de paquetes debe hacerse al construir la imagen.
- rule: Launch Package Management Process in Container
desc: Package management process ran inside container
condition: >
spawned_process
and container
and user.name != "_apt"
and package_mgmt_procs
and not package_mgmt_ancestor_procs
and not user_known_package_manager_in_container
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)
priority: ERROR
tags: [process, mitre_persistence]

Debe cambiarse al formato requerido:

# El contenedor se supone que es inmutable. La gestión de paquetes debe hacerse al construir la imagen.
- rule: Launch Package Management Process in Container
desc: Package management process ran inside container
condition: >
spawned_process
and container
and user.name != "_apt"
and package_mgmt_procs
and not package_mgmt_ancestor_procs
and not user_known_package_manager_in_container
output: >
Package management process launched in container %evt.time,%container.id,%container.name,%user.name
priority: ERROR
tags: [process, mitre_persistence]
Para todos los campos disponibles podemos consultar https://falco.org/docs/rules/supported-fields, que debería estar permitido abrir durante el examen.

A continuación verificamos los logs en nuestro formato ajustado:

➜ root@cluster1-node1:/etc/falco# falco | grep "Package management"

06:38:28.077150666: Error Package management process launched in container 06:38:28.077150666,090aad374a0a,nginx,root
06:38:33.058263010: Error Package management process launched in container 06:38:33.058263010,090aad374a0a,nginx,root
06:38:38.068693625: Error Package management process launched in container 06:38:38.068693625,090aad374a0a,nginx,root
06:38:43.066159360: Error Package management process launched in container 06:38:43.066159360,090aad374a0a,nginx,root
06:38:48.059792139: Error Package management process launched in container 06:38:48.059792139,090aad374a0a,nginx,root
06:38:53.063328933: Error Package management process launched in container 06:38:53.063328933,090aad374a0a,nginx,root

Esto se ve mucho mejor. Copia y pega la salida en el archivo /opt/course/2/falco.log en tu terminal principal. El contenido debe limpiarse así:

# /opt/course/2/falco.log
06:38:28.077150666,090aad374a0a,nginx,root
06:38:33.058263010,090aad374a0a,nginx,root
06:38:38.068693625,090aad374a0a,nginx,root
06:38:43.066159360,090aad374a0a,nginx,root
06:38:48.059792139,090aad374a0a,nginx,root
06:38:53.063328933,090aad374a0a,nginx,root
06:38:58.070912841,090aad374a0a,nginx,root
06:39:03.069592140,090aad374a0a,nginx,root
06:39:08.064805371,090aad374a0a,nginx,root
06:39:13.078109098,090aad374a0a,nginx,root
06:39:18.065077287,090aad374a0a,nginx,root
06:39:23.061012151,090aad374a0a,nginx,root

Para unas pocas entradas debería ser rápido simplemente limpiarlo manualmente. Si hay grandes cantidades de entradas podríamos hacer:

cat /opt/course/2/falco.log.dirty | cut -d" " -f 9 > /opt/course/2/falco.log

La herramienta cut dividirá la entrada en campos usando espacio como delimitador (-d""). Luego solo seleccionamos el noveno campo usando -f 9.

Reglas locales de falco

También hay un archivo /etc/falco/falco_rules.local.yaml en el que podemos anular las reglas predeterminadas existentes. Esta es una solución mucho más limpia para producción. Elige la forma más rápida para ti en el examen si no se especifica nada en la tarea.