Seguridad en Tiempo de Ejecución con Falco
Falco es un motor de detección de amenazas en tiempo de ejecución de código abierto desarrollado por Sysdig que monitoriza las llamadas al sistema (syscalls) en el kernel Linux para detectar comportamientos anómalos en contenedores y Kubernetes, como accesos no autorizados a archivos, ejecución de shells inesperados o cambios en privilegios. A diferencia de los escáneres estáticos, Falco detecta amenazas activas durante la ejecución, completando la postura de seguridad de contenedores. Esta guía cubre el despliegue de Falco y la configuración de reglas y alertas.
Requisitos Previos
- Linux con kernel 4.14+ (Ubuntu 22.04, Debian 12, CentOS 9 o Rocky 9)
- Acceso al kernel (driver de kernel de Falco o eBPF)
- Mínimo 2 GB de RAM y 1 CPU
- Para Kubernetes: Helm 3 instalado
- Cabeceras del kernel instaladas (para compilar el módulo)
Instalación de Falco
# Ubuntu/Debian: instalar cabeceras del kernel primero
apt-get install -y linux-headers-$(uname -r)
# Añadir el repositorio de Falco
curl -fsSL https://falco.org/repo/falcosecurity-packages.asc | \
gpg --dearmor -o /usr/share/keyrings/falco-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/falco-archive-keyring.gpg] \
https://download.falco.org/packages/deb stable main" | \
tee /etc/apt/sources.list.d/falcosecurity.list
apt-get update && apt-get install -y falco
# CentOS/Rocky Linux
rpm --import https://falco.org/repo/falcosecurity-packages.asc
cat > /etc/yum.repos.d/falcosecurity.repo << 'EOF'
[falcosecurity]
name=Falco repository
baseurl=https://download.falco.org/packages/rpm/stable/$basearch
enabled=1
gpgcheck=1
gpgkey=https://falco.org/repo/falcosecurity-packages.asc
EOF
dnf install -y falco
# Durante la instalación, elegir el driver:
# 1. kmod (módulo de kernel) - más compatible
# 2. ebpf - más moderno y sin reinicio necesario
# 3. modern-ebpf - solo kernels recientes (5.8+)
# Configurar el driver eBPF (si se eligió durante la instalación)
falco-driver-loader bpf
# Verificar la instalación
falco --version
# Iniciar el servicio
systemctl enable --now falco
systemctl status falco
Configuración de Reglas
Falco viene con un conjunto de reglas predeterminadas en /etc/falco/falco_rules.yaml:
# Ver las reglas activas
cat /etc/falco/falco_rules.yaml | grep "^- rule:" | head -20
# Estructura de una regla Falco
# - rule: Nombre de la regla
# desc: Descripción de lo que detecta
# condition: Condición de detección (basada en syscalls y campos)
# output: Mensaje de alerta con campos de contexto
# priority: Criticidad (DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL)
# tags: Categorías de la regla
# Configuración principal de Falco
cat /etc/falco/falco.yaml
Configurar la salida de alertas en /etc/falco/falco.yaml:
# Editar la sección de outputs en falco.yaml
# Las alertas pueden enviarse a: stdout, archivo, syslog, programa, HTTP
cat > /etc/falco/falco.yaml << 'EOF'
# Configuración de reglas
rules_file:
- /etc/falco/falco_rules.yaml
- /etc/falco/falco_rules.local.yaml # Reglas personalizadas (sobrescriben/añaden)
# Nivel mínimo de prioridad para generar alertas
priority: warning
# Búfer del log para alta velocidad de eventos
buffered_outputs: false
# Salida a la consola/stdout
stdout_output:
enabled: true
# Salida a archivo de log
file_output:
enabled: true
keep_alive: false
filename: /var/log/falco/falco.log
# Salida a syslog
syslog_output:
enabled: false
# Salida a programa externo (para alertas personalizadas)
program_output:
enabled: false
keep_alive: false
program: "jq '{text: .output}' | curl -d @- -X POST https://hooks.slack.com/services/XXX/YYY/ZZZ"
# Salida HTTP/webhook
http_output:
enabled: false
url: http://localhost:2801/
# Estadísticas de rendimiento
metrics:
enabled: true
interval: 1h
EOF
Reglas Personalizadas
Crea reglas personalizadas en /etc/falco/falco_rules.local.yaml:
cat > /etc/falco/falco_rules.local.yaml << 'EOF'
# Reglas personalizadas locales - sobrescriben o complementan las predeterminadas
# DESACTIVAR reglas predeterminadas demasiado ruidosas
- rule: Read sensitive file untrusted
condition: >
sensitive_files and open_read
and not proc.name in (trusted_programs)
and not container.image.repository in (allowed_images)
enabled: false # Demasiados falsos positivos en nuestro entorno
# NUEVA REGLA: Detectar acceso a datos de configuración sensibles
- rule: Acceso a archivos de credenciales en contenedor
desc: >
Detecta cuando un proceso dentro de un contenedor accede a archivos
que típicamente contienen credenciales o secretos
condition: >
open_read and container
and (fd.name glob "/etc/passwd" or
fd.name glob "/etc/shadow" or
fd.name glob "*.pem" or
fd.name glob "*.key" or
fd.name glob "*id_rsa*")
and not proc.name in (sshd, sudo, gpg)
output: >
Acceso a archivo de credenciales detectado en contenedor
(usuario=%user.name proceso=%proc.name archivo=%fd.name
contenedor=%container.name imagen=%container.image.repository)
priority: WARNING
tags: [security, credenciales]
# NUEVA REGLA: Shell inesperado en contenedor de producción
- rule: Shell ejecutado en contenedor de aplicacion
desc: Detecta la ejecución de shells interactivos en contenedores de aplicación
condition: >
spawned_process and container
and shell_procs
and not container.image.repository in (
"docker.io/library/busybox",
"alpine"
)
and proc.pname != "runc"
output: >
Shell ejecutado en contenedor de aplicación (POSIBLE INTRUSIÓN)
(usuario=%user.name shell=%proc.name contenedor=%container.name
imagen=%container.image.repository pid=%proc.pid)
priority: ERROR
tags: [security, shell, intrusion]
# NUEVA REGLA: Descarga de herramientas en contenedor
- rule: Herramienta de red descargada en contenedor
desc: Detecta la descarga de herramientas potencialmente peligrosas
condition: >
spawned_process and container
and proc.name in (curl, wget, nc, ncat, nmap, masscan)
and not container.image.repository in (allowed_network_tools_images)
output: >
Herramienta de red ejecutada en contenedor
(herramienta=%proc.name contenedor=%container.name args=%proc.args)
priority: WARNING
tags: [security, network, tools]
EOF
# Validar las reglas personalizadas
falco --validate /etc/falco/falco_rules.local.yaml
# Recargar Falco con las nuevas reglas
systemctl restart falco
# Verificar que las reglas se cargaron
falco --list | grep "Acceso a archivos"
Sistema de Alertas
# Ver las alertas en tiempo real
journalctl -u falco -f
# Formato JSON de las alertas (útil para parsear)
# Las alertas tienen este formato:
# {
# "output": "18:30:00.000000000: Warning Shell ejecutado...",
# "priority": "Warning",
# "rule": "Shell ejecutado en contenedor de aplicacion",
# "time": "2024-01-15T18:30:00.000000000Z",
# "output_fields": {
# "container.name": "webapp",
# "proc.name": "bash",
# ...
# }
# }
# Habilitar salida en formato JSON en falco.yaml:
# json_output: true
# json_include_output_property: true
# Contar alertas por tipo en las últimas 24 horas
journalctl -u falco --since "24 hours ago" | \
grep "^.*Warning\|Error\|Critical" | \
awk '{print $NF}' | sort | uniq -c | sort -rn
Integración con Slack y Webhooks
# Script de reenvío de alertas Falco a Slack
cat > /usr/local/bin/falco-to-slack.sh << 'SCRIPT'
#!/bin/bash
SLACK_WEBHOOK_URL="${SLACK_WEBHOOK_URL:?Variable no definida}"
MIN_PRIORITY="${MIN_PRIORITY:-WARNING}" # Solo alertar para WARNING o superior
# Leer la alerta de la entrada estándar (enviada por Falco)
ALERT=$(cat)
# Extraer campos de la alerta JSON
PRIORITY=$(echo "$ALERT" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('priority','UNKNOWN'))")
RULE=$(echo "$ALERT" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('rule','Unknown rule'))")
OUTPUT=$(echo "$ALERT" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('output','No output'))")
# Determinar el color del mensaje según la prioridad
case "$PRIORITY" in
CRITICAL|ERROR) COLOR="#FF0000" ;; # Rojo
WARNING) COLOR="#FFA500" ;; # Naranja
NOTICE) COLOR="#FFFF00" ;; # Amarillo
*) COLOR="#808080" ;; # Gris
esac
# Enviar mensaje a Slack
curl -s -X POST "$SLACK_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "{
\"attachments\": [{
\"color\": \"$COLOR\",
\"title\": \"Alerta de Seguridad Falco: $RULE\",
\"text\": \"\`\`\`$OUTPUT\`\`\`\",
\"footer\": \"Falco Runtime Security\",
\"ts\": $(date +%s)
}]
}"
SCRIPT
chmod +x /usr/local/bin/falco-to-slack.sh
# Configurar Falco para usar el script (en falco.yaml):
# program_output:
# enabled: true
# keep_alive: false
# program: "SLACK_WEBHOOK_URL=https://hooks.slack.com/services/XXX /usr/local/bin/falco-to-slack.sh"
Despliegue en Kubernetes
# Instalar Falco en Kubernetes con Helm
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update
# Instalar Falco como DaemonSet (se ejecuta en cada nodo)
helm install falco falcosecurity/falco \
--namespace falco \
--create-namespace \
--set driver.kind=ebpf \
--set falcosidekick.enabled=true \
--set falcosidekick.config.slack.webhookurl="https://hooks.slack.com/services/XXX" \
--set falcosidekick.config.slack.minimumpriority="warning"
# Verificar el despliegue
kubectl get pods -n falco
kubectl logs -n falco -l app.kubernetes.io/name=falco -f
# Ver las alertas de Falco en Kubernetes
kubectl logs -n falco -l app.kubernetes.io/name=falco | \
grep -E "Warning|Error|Critical"
# Desplegar reglas personalizadas como ConfigMap
kubectl create configmap falco-custom-rules \
--from-file=custom-rules.yaml=/etc/falco/falco_rules.local.yaml \
-n falco
# Referenciar el ConfigMap en el Helm chart
helm upgrade falco falcosecurity/falco \
--namespace falco \
--set customRules."custom-rules\.yaml"="$(cat /etc/falco/falco_rules.local.yaml)"
Respuesta a Incidentes
# Script de respuesta automática a alertas críticas de Falco
cat > /usr/local/bin/falco-incident-response.sh << 'SCRIPT'
#!/bin/bash
# Respuesta automática: aislar contenedor comprometido
ALERT=$(cat)
CONTAINER_ID=$(echo "$ALERT" | python3 -c "
import sys, json
d = json.load(sys.stdin)
fields = d.get('output_fields', {})
print(fields.get('container.id', ''))
")
if [ -z "$CONTAINER_ID" ] || [ "$CONTAINER_ID" = "<NA>" ]; then
exit 0
fi
PRIORITY=$(echo "$ALERT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('priority',''))")
# Solo actuar en alertas de máxima criticidad
if [ "$PRIORITY" = "CRITICAL" ] || [ "$PRIORITY" = "ERROR" ]; then
echo "[$(date)] RESPUESTA: Pausando contenedor comprometido $CONTAINER_ID"
# Pausar el contenedor (congelar sin eliminar, preservar evidencia)
docker pause "$CONTAINER_ID" 2>/dev/null
# Capturar el estado del proceso para análisis forense
docker top "$CONTAINER_ID" > /var/log/falco/incident-${CONTAINER_ID}-procs.txt 2>/dev/null
docker inspect "$CONTAINER_ID" > /var/log/falco/incident-${CONTAINER_ID}-inspect.json 2>/dev/null
# Enviar notificación de incidente
logger -t falco-incident "INCIDENTE: Contenedor $CONTAINER_ID aislado por alerta de seguridad"
fi
SCRIPT
chmod +x /usr/local/bin/falco-incident-response.sh
Solución de Problemas
# Ver estado del servicio y logs
systemctl status falco
journalctl -u falco -n 50 --no-pager
# Verificar que el driver está cargado
lsmod | grep falco # Para módulo de kernel
# o para eBPF:
ls -la /sys/kernel/debug/tracing/events/ | grep falco
# Probar que Falco detecta eventos (generar un evento de prueba)
# En una terminal, iniciar Falco con verbose:
falco --list # Listar todas las reglas activas
# En otra terminal, ejecutar algo que debería generar alerta:
docker run --rm -it alpine sh -c "cat /etc/shadow"
# Debe aparecer alerta en los logs de Falco
# Validar archivo de reglas
falco --validate /etc/falco/falco_rules.yaml
falco --validate /etc/falco/falco_rules.local.yaml
# Ver las macros y listas disponibles en las reglas
falco --list -a | grep macro
# Problema de rendimiento: Falco consume demasiada CPU
# Revisar las reglas más activas
falco --stats-interval 5 2>&1 | grep "events/s"
Conclusión
Falco proporciona visibilidad en tiempo real sobre el comportamiento de contenedores y workloads Kubernetes, detectando intrusiones y comportamientos anómalos que los escáneres de vulnerabilidades estáticos no pueden identificar. La combinación de reglas predefinidas mantenidas por la comunidad con reglas personalizadas adaptadas a tu infraestructura, junto con la integración con sistemas de alerta como Slack, convierte a Falco en una pieza esencial de cualquier estrategia de seguridad en tiempo de ejecución para entornos de contenedores en producción.


