Um exploit de escalada local de privilégios divulgado na sexta-feira (16) concede acesso root ao OpenBSD 7.9 ao encadear um estouro de inteiro (integer overflow) com cerca de 37 anos de existência e uma falha separada do kernel. A técnica contorna o KARL (Kernel Address Randomized Link), mecanismo de randomização de endereços do kernel do OpenBSD, além das proteções de hardware SMAP (Supervisor Mode Access Prevention) e SMEP (Supervisor Mode Execution Prevention).
A empresa de segurança Calif, que encontrou e reportou as falhas, publicou um relatório detalhado e o código completo de prova de conceito (PoC) depois que o OpenBSD lançou correções para os dois problemas em setembro.
O estouro de inteiro na função de anexação shmat(4) foi corrigido na errata 018, lançada em 14 de setembro como correção de confiabilidade. A falha de uso após liberação de memória, com contagem de referências, que completa a cadeia, foi corrigida separadamente na errata 026, lançada em 30 de setembro como correção de segurança.
Ambas estão disponíveis pelo syspatch e abrangem todas as arquiteturas. O OpenBSD 7.8 também recebeu a correção do estouro de inteiro. Esse estouro, ponto de entrada de toda a cadeia, é classificado como correção de confiabilidade, e não de segurança.
Até a publicação, nenhum CVE (Common Vulnerabilities and Exposures, identificador padronizado de vulnerabilidades) havia sido atribuído a nenhuma das duas falhas. Não há evidências de que as vulnerabilidades tenham sido usadas em ataques.
O contador de anexações de memória compartilhada shm_nattch é definido como um tipo short com sinal de 16 bits, com valor máximo de 32.767, nas fontes originais do BSD (Berkeley Software Distribution), datadas de 1988. O OpenBSD herdou o tipo e nunca o ampliou.
O exploit mapeia 127 segmentos de memória compartilhada e cria 259 processos, levando o contador além do seu valor máximo e fazendo-o dar a volta para -32.643. Em seguida, uma condição de corrida dispara um uso após liberação de memória: a contagem de referências corrompida faz o kernel liberar memória que outros processos ainda utilizam.
Uma escrita fora dos limites, separada, sobrescreve contadores de associação a grupos multicast no kernel. Quando o socket afetado é fechado, os decrementos resultantes modificam entradas da tabela de páginas, alterando um mapeamento de memória do usuário para acessível ao supervisor e contornando SMAP e SMEP. Depois, o exploit sobrescreve um ponteiro de função em um endereço previsível do kernel para executar o próprio código.
“Embora o KARL do OpenBSD relinke o binário do kernel para randomizar tanto os endereços de funções quanto os de dados, os alocadores de memória do kernel continuam determinísticos”, escreveu o pesquisador Andrew Griffiths. Tanto o alocador de inicialização quanto o alocador de melhor ajuste (best-fit) não têm randomização do endereço-base. Assim, estruturas criadas durante o boot, incluindo ponteiros de função nos manipuladores das interfaces de rede lo0 e enc0, ficam nos mesmos endereços entre reinicializações no mesmo hardware. O exploit não depende de nenhuma vulnerabilidade de divulgação de informações.
Além das duas correções, a Calif propõe quatro categorias de endurecimento de segurança: desvinculação segura (safe unlinking) para listas encadeadas do kernel, já usada pelo FreeBSD e pelo NetBSD; randomização mapeamento autorreferencial da tabela de páginas; randomização do alocador do kernel; e verificação de limites baseada no compilador.
A Calif afirmou ter reportado as falhas ao OpenBSD “no início deste ano”. O código de prova de conceito do exploit está disponível no GitHub.