eBPF: como o Linux detecta ataques pelo comportamento

Entenda o que é eBPF, como ele permite ao Linux detectar ataques pelo comportamento dos programas e teste na prática com um único comando no terminal.

Compartilhar
eBPF: como o Linux detecta ataques pelo comportamento

Imagine um prédio com um porteiro que tem uma pasta cheia de fotos de criminosos conhecidos. Toda vez que alguém chega, ele compara o rosto com as fotos. Se bater, barra. Se não bater, libera.

Funciona bem, até o dia em que o ladrão aparece de boné e óculos escuros.

É assim que boa parte das ferramentas de segurança tradicionais funciona: elas comparam um arquivo com uma lista de ameaças já conhecidas (as chamadas assinaturas). Se o atacante mudar o arquivo um pouquinho, a comparação falha.

Agora imagine um segundo segurança, que não liga para o rosto de ninguém. Ele só observa o que as pessoas fazem. O entregador que, em vez de deixar a encomenda, começa a testar maçanetas no corredor do quinto andar? Esse chama atenção, com ou sem disfarce.

Essa é a ideia da detecção por comportamento. E no Linux, a tecnologia que tornou isso viável se chama eBPF.

Este guia é baseado num excelente artigo do Rodrigo Freire no TabNews, que explica o assunto para quem está começando.

Programa nenhum mexe em nada sozinho

Para entender o eBPF, primeiro precisamos entender quem manda no computador.

Num sistema operacional, quem controla o hardware (disco, rede, memória) é o kernel, o núcleo do sistema. Um programa comum não tem permissão para ler um arquivo direto no disco nem para abrir uma conexão de rede por conta própria. Ele precisa pedir para o kernel.

Esse pedido se chama syscall (chamada de sistema). Pense no kernel como o balcão de atendimento de uma repartição: ninguém entra no arquivo morto, todo mundo pede no guichê.

Alguns exemplos:

O programa quer... Syscall
Abrir um arquivo openat
Iniciar outro programa execve
Conectar num servidor connect

Tudo que um programa faz de relevante passa por uma dessas chamadas, sem exceção.

Por que isso importa para a segurança

Imagine que um atacante invadiu um site seu e plantou um script malicioso. Ele pode escrever esse script de mil formas diferentes, trocar nomes de variáveis, embaralhar o código, apagar rastros.

Mas, no fim das contas, o que o script quer fazer é sempre parecido: executar comandos, ler arquivos de senha e mandar dados para fora. E isso exige as mesmas syscalls, não importa como o código foi escrito.

Então, em vez de perguntar "esse arquivo é conhecido?", dá para perguntar: "esse programa está pedindo coisas que não combinam com o trabalho dele?"

Um servidor web que de repente abre um terminal e lê o arquivo .env (onde costumam ficar senhas e chaves de API) não precisa estar numa lista de vírus para levantar suspeita.

Para fazer essa pergunta, alguém precisa enxergar as syscalls. É aí que entra o eBPF.

Então, o que é eBPF?

O eBPF é um recurso do kernel Linux que permite rodar pequenos programas dentro do próprio kernel, ligados a eventos específicos.

Na prática, você consegue pedir algo como: "toda vez que alguém chamar a syscall execve, rode o meu programinha e me conte quem pediu e qual arquivo foi executado".

Voltando à repartição: é como instalar uma câmera discreta em cima do guichê, que anota cada pedido feito, sem atrasar a fila.

Como era antes do eBPF

As alternativas antigas tinham problemas sérios:

  • strace: mostra as syscalls, mas desacelera muito o programa observado e acompanha um processo de cada vez. Não serve para vigiar um servidor inteiro.
  • auditd: tem visão mais ampla, mas com muitas regras gera um volume enorme de log e pesa no sistema.
  • Módulo de kernel: dá acesso total, só que qualquer erro seu pode travar a máquina inteira. É como dar a chave mestra do prédio para um estagiário no primeiro dia.

O verificador: o segurança do segurança

O eBPF resolve boa parte disso com um verificador. Antes de aceitar o seu programa, o kernel checa se o código é seguro: se não tem laço infinito, se não acessa memória que não deveria. Se reprovar, o programa nem carrega.

Não é perfeito (já apareceram falhas no próprio verificador), mas o modelo é muito mais seguro do que escrever um módulo de kernel.

E tem mais: como lembrou um leitor nos comentários do artigo original, o eBPF conta com um compilador JIT no kernel, que transforma o programa em código nativo da máquina. Na prática, ele roda praticamente com a mesma velocidade de um programa comum. Em placas de rede compatíveis, dá até para executar o programa eBPF direto na placa, sem gastar CPU.

Mão na massa: veja tudo o que roda no seu Linux

Chega de teoria. Para ver o eBPF funcionando, use o bpftrace, uma ferramenta que permite escrever programas eBPF em uma linha. Faça isso numa máquina de teste, VM ou no seu homelab.

Instale o bpftrace na sua distro:

# Debian, Ubuntu, Mint
sudo apt install bpftrace

# Arch Linux
sudo pacman -S bpftrace

# Fedora
sudo dnf install bpftrace

Agora rode o comando abaixo, que observa toda chamada execve (ou seja, todo programa iniciado):

sudo bpftrace -e 'tracepoint:syscalls:sys_enter_execve { printf("%s executou %s\n", comm, str(args->filename)); }'

Deixe rodando e abra outro terminal para digitar comandos qualquer, como ls ou cat. Cada programa iniciado aparece na tela, junto com o nome de quem pediu.

Num servidor, vale deixar uns minutos e só observar a saída. Como o autor do artigo original avisa, quase sempre aparece coisa que você não sabia que rodava. Para sair, aperte Ctrl + C.

Do evento solto à detecção de ataque

Um evento isolado quase nunca diz muita coisa. Um servidor web executando sh pode ser suspeito, mas também pode ser um script legítimo de manutenção.

O que faz a diferença é o contexto: quem iniciou esse processo, e quem iniciou o processo que o iniciou. É como uma árvore genealógica dos programas.

Por isso, sistemas de defesa baseados em eBPF guardam a árvore de processos, atualizada a cada vez que um processo cria outro. Veja este exemplo:

php-fpm  →  sh  →  curl (conectando num IP nunca visto antes)

Cada passo, sozinho, parece normal. O PHP às vezes chama comandos. O curl faz requisições o tempo todo. Mas a sequência inteira tem cara de invasão. E como a árvore está registrada, dá para subir até a origem do ataque e encontrar tudo que veio dali, em vez de matar só a ponta.

Sem conhecer o normal, tudo vira alarme

Tem um detalhe que separa ferramenta boa de ferramenta irritante: é preciso saber o que é normal na máquina que você está protegendo. Uma ferramenta que não aprende o comportamento normal dispara alarme falso o dia inteiro, e a equipe acaba desligando.

É como o alarme de carro que dispara com qualquer vento: depois da décima vez, ninguém mais olha pela janela.

Detectar não é o mesmo que bloquear

Observar é relativamente simples. Bloquear com segurança é outra história.

O problema tem nome: TOCTOU (time of check to time of use, ou "verifica num momento, usa em outro"). Funciona assim: o caminho do arquivo que o programa quer abrir fica na memória do próprio programa. Uma outra parte dele pode trocar esse caminho depois que você checou e antes do kernel usar. Você aprova a abertura de um arquivo inofensivo e o kernel abre outro.

É como conferir a identidade de uma pessoa na portaria e, enquanto você olha para o lado, ela entregar o crachá para outra.

A solução é decidir num ponto em que o kernel já resolveu o caminho e trabalha com a própria cópia. O BPF LSM faz exatamente isso: ele conecta o programa eBPF nos mesmos ganchos de segurança usados pelo SELinux e pelo AppArmor. O custo é exigir um kernel recente com CONFIG_BPF_LSM ativado e o bpf na lista de módulos de segurança carregados no boot, o que nem toda distribuição traz de fábrica.

Para conferir quais módulos de segurança estão ativos no seu sistema:

cat /sys/kernel/security/lsm

Se bpf aparecer na lista, o seu kernel está pronto para o BPF LSM.

Os limites do eBPF

Nenhuma tecnologia é bala de prata, e o eBPF também tem limites claros:

  • Ele vê o que passa pelo kernel. Não enxerga o que acontece só dentro da memória de um programa, nem lê tráfego criptografado.
  • Quem tem acesso root pode descarregar o seu programa de monitoramento. Proteger o próprio agente de segurança faz parte do projeto.
  • Kernels antigos podem não ter os recursos necessários.
  • O custo de desempenho varia conforme o que você observa. Meça no seu caso em vez de confiar em número de artigo.

Ferramentas prontas para conhecer

Se você quer usar essa ideia sem escrever tudo do zero, existem projetos open source maduros baseados em eBPF:

  • Falco: detecção de comportamento suspeito em servidores e containers.
  • Tetragon: observabilidade e aplicação de regras de segurança em tempo real.
  • Tracee: rastreamento de eventos e detecção de ameaças.

O autor do artigo original também mantém o SyscallCage, um projeto open source que usa o BPF LSM justamente para bloquear com segurança.

Mas o conselho dele é o melhor ponto de partida: antes de instalar qualquer coisa, rode o comando do bpftrace e olhe a saída. É a forma mais rápida de entender o que o seu computador faz o tempo todo sem você ver.

Monte suas camadas de defesa

O eBPF é uma camada poderosa, mas segurança de verdade funciona em camadas, como as muralhas de um castelo. Se você tem um servidor ou homelab, combine com o que já mostramos aqui no blog:

E para quem quer ir além, outro artigo do TabNews desta semana explica como criar honeypots em redes internas: portas falsas que nenhum aparelho legítimo deveria acessar. Se alguém bater nelas, você sabe que tem algo varrendo a sua rede. É a mesma filosofia do eBPF aplicada à rede: não importa quem é, importa o que está fazendo.