Desmistificando o Falco
O que é o Falco?
Antes de definir o que é o Falco, vou usar a analogia em inglês do site oficial:
Você pode pensar no Falco como uma rede de câmeras de segurança para a sua infraestrutura.
E o que isso significa de forma técnica? O Falco é uma ferramenta que coleta dados/eventos (syscalls do Kernel Linux ou outras fontes externas) avalia esses dados coletados a partir de um conjunto de regras e te notifica se algo ruim ou anormal acontecer (no futuro devo falar do Falco Sidekick), e tudo isso, em tempo real.
O Falco disponibiliza um conjunto dessas regras prontas para uso, feitas especificamente para Kubernetes, Linux e cloud, é só instalar e usar.
E falando um pouco do projeto, o Falco foi originalmente desenvolvido pela Sysdig e em 2018 foi doado para a CNCF. Em 2020 foi para o status de encubado e recentemente em 2024 foi graduado.
Ok, mas como o Falco funciona?
O falco é composto pelos seguintes componentes:
- Event Sources
- Rules
- Outputs
- Plugins
Sendo que,
Event Sources
O falco suporte diferentes fontes de eventos que são usados como entrada para comparar com as regras.
Nativamente suporta eventos vindos de syscalls
(consumindo eventos do kernel linux) e por meio do sistema de plugins suporta eventos de outras fontes, como:
- Docker
- Kubernetes
- Nomad
- Cloudtrail
Rules
São efetivamente as regras que o Falco usa para avaliar os eventos, é baseado nisso que um evento é considerado normal ou anormal.
Um arquivo de uma regra é um yaml
contendo três elementos principais:
Rules
Macros
Lists
Um exemplo de regra usando os três elementos:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- list: shell_binaries
items: [bash, csh, ksh, sh, tcsh, zsh, dash]
- macro: shell_procs
condition: proc.name in (shell_binaries)
- rule: shell_in_container
desc: notice shell activity within a container
condition: >
spawned_process and
container and
shell_procs
output: >
shell in a container
(user=%user.name container_id=%container.id container_name=%container.name
shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline)
priority: WARNING
Nesse exemplo, estamos avaliando todos os eventos de shell em um container que usaram bash
, csh
, ksh
, tcsh
, zsh
ou dash
e gerando um alerta com a prioridade WARNING
.
É importante mencionar, que você pode criar suas regras customizadas e específicas para a sua organização (isso que torna o Falco tão poderoso).
Outputs
De forma nativa, o Falco pode enviar alertas para os seguintes canais:
- Saída padrão (
stdout
) - Um arquivo
- Syslog
- Um endpoint http/https (útil pra webhook)
- Um client via gRPC
Se você quiser estender isso, pode usar o Falco Sidekick, que permite que você envie para muitas outras ferramentas, como:
- Slack
- Ms Teams
- Loki
- Alertmanager
e muitos outros. O Falco Sidekick pode ser habilitado junto da instalação do Falco, ou instalado separadamente.
E como faço a instalação do Falco?
O falco pode ser instalado de algumas formas:
- em cluster Kubernetes
- como container
- como pacote em um host (deb, rpm)
- como tarball em um host
E pra outros ambientes mais específicos, você pode consultar as instruções aqui.
Pra esse caso, vou usar como exemplo a instalação em um cluster Kubernetes, usando o Helm chart oficial:
1
2
3
# adicionando o repositório do chart
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update
1
2
# instalando o helm chart
helm upgrade --install falco --namespace falco --create-namespace --set tty=true falcosecurity/falco
1
2
#checando se os pods estão saudáveis
kubectl get pods -n falco
Depois disso, podemos gerar um evento para validar os alertas:
1
2
3
#criando um deployment e executando um comando shell dentro do pod
kubectl create deployment nginx --image=nginx
kubectl exec -it $(kubectl get pods --selector=app=nginx -o name) -- cat /etc/shadow
E checando os logs:
1
2
kubectl logs -l app.kubernetes.io/name=falco -n falco -c falco | grep Warning
Você deve ver um alerta do tipo:
1
2
11:01:05.743481343: Warning Sensitive file opened for reading by non-trusted program (file=/etc/shadow gparent=systemd ggparent=<NA> gggparent=<NA> evt_type=openat user=root user_uid=0 user_loginuid=-1 process=cat proc_exepath=/usr/bin/cat parent=containerd-shim command=cat /etc/shadow terminal=34816 container_id=bf74f1749e23 container_image=docker.io/library/nginx container_image_tag=latest container_name=nginx k8s_ns=default k8s_pod_name=nginx-7854ff8877-h97p4)
Você pode checar todas as regras disponíveis para uso aqui.
Próximos passos?
Você deve estar pensando: incrível! consigo detectar ameaças (ou comportamentos anormais) e notificar, mas teria alguma forma de responder/remediar?
E aí que entra mais um componente do ecossistema do Falco: o Falco Talon.
O Talon recebe os eventos diretamente do Falco ou do Falco Sidekick e baseado em uma regra toma uma ação de remediação, por exemplo “matar” um Pod.
Um exemplo de uma política do Talon:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
- action: Terminate Pod
description: terminate the pod if it doesn't belong to a statefulset
actionner: kubernetes:terminate
parameters:
ignoreDaemonsets: false
ignoreStatefulsets: true
- action: Disable outbound connections
actionner: kubernetes:networkpolicy
parameters:
allow:
- "192.168.1.0/24"
- "172.17.0.0/16"
- "10.0.0.0/32"
- rule: Suspicious outbound connection
description: Block suspicious outbound connections and terminate the pod
match:
rules:
- Unexpected outbound connection destination
actions:
- action: Disable outbound connections
ignore_errors: true
- action: Terminate Pod
parameters:
gracePeriods: 2
Onde temos duas actions:
Terminate Pod
Disable outbound connections
Sendo que essas actions são ativadas em resposta a regra do Falco chamada Unexpected outbound connection destination
.
Por agora é isso, para mais informações, recomendo dar uma olhada na documentação do Falco!