O projeto Openwall publicou o módulo do núcleo LKRG 1.0.0 (Linux Kernel Runtime Guard), destinado a verificar a integridade das estruturas do núcleo e identificar tentativas de exploração de vulnerabilidades no núcleo. Vale ressaltar que a atribuição do número da versão 1.0.0 marca a maturidade do projeto. O código do projeto é distribuído sob a licença GPLv2.
O módulo é adequado tanto para proteger contra ataques, manipulando vulnerabilidades já conhecidas no núcleo do Linux, quanto para se opor a exploits que utilizam vulnerabilidades ainda desconhecidas, desde que não sejam aplicadas medidas especiais para contornar o LKRG. A proteção é baseada na detecção de alterações não autorizadas no núcleo ativo (verificação de integridade) e no monitoramento de alterações nas permissões dos processos de usuário (detecção de aplicação de exploits).
A verificação de integridade é realizada com base na comparação de hashes, calculados para as áreas de memória e estruturas de dados mais importantes do núcleo, como IDT (Interrupt Descriptor Table), MSR, tabelas de chamadas de sistema, todas as rotinas e funções, manipuladores de interrupção, listas de módulos carregados, conteúdo da seção “.text” dos módulos e atributos dos processos. O procedimento de verificação é ativado periodicamente por um temporizador ou na ocorrência de certos eventos no núcleo, por exemplo, ao executar chamadas de sistema setuid, setreuid, fork, exit, execve e do_init_module.
A detecção de possíveis aplicações de exploits e a bloqueio de ataques ocorrem antes que o núcleo conceda acesso a recursos (por exemplo, antes da abertura de um arquivo), mas após a obtenção de permissões não autorizadas pelo processo (por exemplo, troca de UID). Ao detectar comportamento não autorizado dos processos, eles são forçosamente finalizados, o que é suficiente para bloquear muitos exploits. Os custos operacionais do módulo são estimados em 2-2,5%.
Compatibilidade com sistemas com arquiteturas x86-64, AArch64 (ARM64), ARM32 e x86. A operação do LKRG 1.0.0 foi testada com núcleos de várias distribuições, começando pelo núcleo 3.10 do RHEL/CentOS 7 e terminando no 6.17-rc4 do repositório em preparação para o lançamento do Fedora 44. Pacotes estão disponíveis para as distribuições ALT Linux, Arch Linux, Astra Linux, Gentoo, Guix, NixOS, Rocky Linux, Whonix, Yocto e OpenBMC. Pacotes compilados para o Rocky Linux podem ser usados no RHEL 8/9 e distribuições derivadas como AlmaLinux 8/9, enquanto pacotes para Whonix estão disponíveis no Debian e Ubuntu.
Entre as mudanças na nova versão:
- Compatibilidade assegurada com núcleos Linux até a versão 6.17-rc4.
- Com a utilização de núcleos a partir da versão 6.13, a interceptação de chamadas remotas override_creds() e revert_creds() foi interrompida, limitando a detecção de ataques que reescrevem o ponteiro cred. As limitações foram tentadas ser compensadas por meio da adição de verificações de reescrita do ponteiro cred em outros locais do núcleo.
- O rastreamento excessivo de credenciais para as quais a verificação de integridade não é realizada foi interrompido. Essa mudança permitiu reduzir a base de código em aproximadamente 1500 linhas.
- Adicionada suporte ao mecanismo introduzido no núcleo Linux 6.10 para criar arquivos temporários no sistema de arquivos OverlayFS, utilizando a opção O_TMPFILE (ovl_tmpfile). O suporte mencionado é necessário para evitar alarmes falsos que ocorrem ao usar contêineres isolados em sistemas com núcleos 6.10-6.12.
- Para sistemas x86_64, adicionada suporte à tecnologia Intel CET (Control-flow Enforcement Technology) para proteção de código executável utilizando instruções IBT (indirect branch tracking), além da proteção de software kCFI (kernel Control Flow Integrity) para bloquear a violação da ordem normal de execução (control flow) devido à exploração que modifica ponteiros de funções armazenados na memória.
- Para a conexão de muitos manipuladores, o mecanismo kprobes foi utilizado em vez de kretprobes, simplificando o código de instalação de hooks e permitindo alcançar um desempenho mais alto.
- O trabalho com bloqueios (lock) de dados específicos para o processo (per-task shadow data) foi reestruturado. Ao excluir bloqueios desnecessários, foi possível aumentar a performance no acesso a esses dados.
- Corrigidos erros que levavam a condições de corrida, problemas de verificação de integridade e alarmes falsos.
- Melhorado o suporte à compilação utilizando Clang.
Fonte: opennet.ru
