Não existem mãos e olhos humanos suficientes para acompanhar tudo o que acontece em um sistema operacional — e muito menos em toda uma rede corporativa, onde o fluxo de eventos pode facilmente passar de 3000/seg. Muitos sistemas operacionais já contam com utilitários de log padrão pré-instalados que registram o que acontece no sistema: no Linux é o syslog (e suas várias implementações) e, no Windows, o Windows Event Logs.
Mas muitas vezes a funcionalidade dessas soluções padrão não é suficiente. Por exemplo, no syslog do Linux não há políticas de auditoria que determinem quais informações devem ser coletadas e quais podem ser ignoradas. Para isso existem soluções alternativas específicas.
Como o Auditd funciona?
Auditd é um subsistema de logging que permite usar políticas de auditoria, módulo de kernel e outros componentes de software para registrar eventos no sistema operacional. A composição desse subsistema é a combinação de:
- utilitário cliente auditctl, que passa novas regras para o daemon de configuração;
- daemon auditd, que ocupa soquetes de arquivo para escutar chamadas do auditctl e logs vindos do kernel;
- utilitário ausearch para buscar registros nos logs por parâmetros;
- arquivos de configuração em /etc/audit + plugins + políticas ou regras de auditoria.
Como a execução de praticamente qualquer ação no sistema operacional é acompanhada por uma chamada ao kernel via chamadas de sistema (syscalls), o processo de registro das ações dos “sub-objetos” no SO ocorre da seguinte forma.
Por exemplo, um processo com o servidor SSH decide ocupar um soquete de rede e informa isso ao kernel por meio da chamada de sistema socket(). O kernel, por sua vez, processa a solicitação e gera um registro especificando todos os principais parâmetros da chamada, depois salva esse registro no buffer de auditoria. A partir daí, os logs são enviados por meio do mecanismo de IPC (Inter Process Communication) para o soquete de arquivo que está sendo usado pelo daemon auditd. Dentro dele ocorre o processo de filtragem pelas regras configuradas, e é selecionado o que deve ser efetivamente gravado.
Se necessário, os pacotes filtrados podem ser enviados para servidores de coleta, que repassam os dados a um SIEM ou outros sistemas de proteção. Mas neste artigo vamos analisar exclusivamente o subsistema em um host local.
Como instalar e configurar o Auditd?
Para instalar, basta usar o repositório base, onde o binário do auditd já está incluído. A instalação varia conforme a distribuição. Para distribuições do tipo deb, use o comando:
Para distribuições do tipo rpm, algo como:
Depois disso, o daemon auditd, responsável por escutar e processar os logs, será automaticamente iniciado:
Todo o subsistema é implantado automaticamente e de forma independente do administrador de sistema. Quando tivermos certeza de que o serviço necessário foi iniciado com sucesso, podemos passar à configuração das políticas que vão determinar o que será armazenado dentro do enorme fluxo de eventos existentes. Para isso, abrimos o diretório de regras/políticas; no seu caso, você pode nomear a regra como quiser, desde que o arquivo tenha a extensão .rules:
Vamos analisar cada uma das linhas apresentadas no arquivo de configuração padrão:
- opção -D remove regras previamente adicionadas da memória do serviço, para evitar conflitos;
- opção -b define o tamanho do buffer de auditoria para eventos antes da gravação em arquivo de log;
- opção -backlog_wait_time 60000 define o tempo máximo (em milissegundos) que o daemon de auditoria aguardará o envio de eventos caso o buffer esteja cheio. Neste caso, ele espera até 60 segundos antes de limpar o log à força;
- -f 0 – usar nível mínimo de mensagens (silencioso);
- -f 1 – registrar apenas eventos críticos (saída compacta);
- -f 2 – mensagens mais detalhadas (padrão).
E também a própria regra de política de auditoria, que vai filtrar os eventos necessários dentro do conjunto heterogêneo de eventos.
Como escrever regras para o auditd?
Existem dois tipos principais de escrita de regras no auditd. O primeiro tipo é para monitorar chamadas de sistema relacionadas a arquivos e diretórios:
Essa regra permite registrar solicitações de trabalho com um objeto do sistema de arquivos em modo de escrita e modificação de atributos. A opção -w especifica o caminho para o arquivo monitorado, a opção -p define os atributos de arquivo (rwx) que serão monitorados e a opção -F faz o filtro. Se todas essas condições forem verdadeiras, o evento é gravado no arquivo de log do serviço!
Ou um formato mais estendido do segundo tipo, em que a chamada de sistema e o filtro aplicado ao evento são especificados explicitamente:
Aqui, a opção -a (append) adiciona uma nova regra ao final da lista; a ação always/never determina se o evento será registrado ou não. A opção -S define o tipo de chamada de sistema. Aqui estão as principais:
- open – acesso a um objeto do sistema de arquivos;
- execve – carrega o aplicativo na memória do processo. Pode ser usada para rastrear a inicialização de software, pois a primeira chamada de sistema fork() cria um processo e execve carrega os arquivos na memória do novo processo;
- socket – chamada para criar um soquete para comunicação entre redes ou entre processos;
- listen – chamada para iniciar a escuta de conexões de entrada em um soquete;
- setreuid/setregid – chamadas que implementam elevação ou redução de privilégios para um processo.
Casos de uso reais
Para ferramentas como SIEM/EDR/Zabbix etc., que permitem monitorar o desempenho e a segurança da infraestrutura existente, são necessários logs das máquinas. Vamos considerar a tarefa de rastrear quem executou um contêiner Docker infectado elevando privilégios de usuário comum para root.
Vamos rastrear as chamadas de sistema para iniciar o contêiner com o comando sudo strace -o ss.txt :
A saída é bastante grande; usando o utilitário grep, você pode filtrar por chamadas de sistema importantes a partir do arquivo ss.txt:
Como podemos ver, dois processos com dois PIDs 2545 e 2547 foram iniciados, carregando executáveis a partir dos caminhos /usr/bin/sudo e /usr/bin/docker. Vamos escrever uma regra para o evento encontrado:
-a always,exit -F arch=b64 -S execve -F exe=/usr/bin/sudo -F auid!=0
-a always,exit -F arch=b64 -S execve -F exe=/usr/bin/docker -F auid!=0" | tee -a /etc/audit/rules.d/audit.rules && auditctl -R /etc/audit/rules.d/audit.rules
Após executar o comando para carregar as regras no módulo de kernel do subsistema de logging, é necessário verificar se a operação foi feita corretamente:
No final, conseguimos ver nossas regras carregadas, o que significa que a operação foi bem-sucedida! Vamos iniciar o docker com sudo e coletar os logs no arquivo padrão:
Depois de filtrar a grande quantidade de eventos registrados na pasta de logs, podemos ver chamadas de sistema para execve com um AUID ou UID real diferente de root. Esse evento pode indicar um incidente de segurança da informação que violou a política e, portanto, pode ser um ataque! Os logs são usados para detecção proativa e mitigação de ameaças, bem como para monitorar o estado dos serviços e do sistema como um todo.
Generalizando o algoritmo de funcionamento do serviço, podemos dizer que, quando um processo está sendo executado no sistema operacional, ele gera um grande número de solicitações ao kernel, que podem ser rastreadas. A política de auditoria permite selecionar, dentre milhões de eventos, apenas aqueles mais necessários e importantes, que depois podem ser enviados para ferramentas analíticas ou usados para depuração do sistema.