Uma vulnerabilidade permite que um usuário se torne root mesmo em contêineres. Confira os detalhes dessa exploração.
Recentemente foram divulgadas informações sobre a vulnerabilidade (CVE-2022-29582) na implementação da interface de E/S assíncrona io_uring, incluída no kernel Linux desde a versão 5.1, que permite que um usuário sem privilégios se torne root no sistema, mesmo quando executando uma exploração de contêiner.
Vulnerabilidade permite que um usuário se torne root mesmo em contêineres
Vale ressaltar que a referida vulnerabilidade foi relatada há pouco mais de 3 meses (aproximadamente no início de maio deste ano), mas a informação e divulgação completas foram divulgadas recentemente.
Em relação à vulnerabilidade, é mencionado que ela ocorre ao acessar um bloco de memória já liberado, manifesta-se em kernels Linux da ramificação 5.10.
Essa vulnerabilidade permite que a memória liberada como resultado de uma race condition seja acessada quando os tempos limite são tratados na função io_flush_timeouts(), que remove a entrada de tempo limite da lista e a cancela, sem verificar a criação e exclusão do tempo de espera em esse ponto.
“Uma descrição geral atualizada de io_uring já foi fornecida por outros. Eles explicam isso mil vezes melhor do que nós, então vamos cobrir o subsistema mais extensivamente (veja este artigo Grapl Security e este artigo Flatt Security para uma ótima introdução).”
Mais importante, o campo opcode determina o tipo de operação a ser executada. Para cada “opcode” que o requer, o campo fd especifica o descritor de arquivo no qual executar a E/S solicitada.
Quase todas as chamadas de sistema de E/S normais (read, sendto, etc.) têm um opcode assíncrono equivalente. Cada campo pode assumir diferentes funções dependendo da operação.
“Uma vez recuperado do SQ, um SQE é convertido em uma representação interna descrita por struct io_kiocb(retorno de chamada de entrada/saída do kernel). Esses objetos são comumente conhecidos como solicitações.”
“struct io_kiocb é usado como um equivalente ao SQE “ready-for-launch” no qual se baseia, em que qualquer descritor de arquivo é resolvido para struct file*s, as credenciais do usuário são anexadas, a personalidade é anexada (no qual os núcleos serão executados), etc”
Após a conclusão da operação solicitada, uma entrada correspondente ao SQE é gravada na fila de conclusão (CQ). Essa entrada é chamada de entrada da fila de conclusão (CQE) e contém campos como um código de erro e um valor de resultado. O aplicativo de espaço do usuário pode sondar o CQ para novas entradas para determinar se os SQEs enviados concluíram o processamento e qual foi o resultado.
É mencionado que existem alguns cenários em que é fácil substituir um objeto em tempo real. Mas há duas limitações:
- LT’ deve ser atribuído e inicializado em uma janela de corrida. Ou seja, após o LT ser liberado, mas antes de chegar a um ponto do LT que não é mais acessado.
- LT’ só pode ser outro objeto struct io_kiocb. Devido ao isolamento do heap, onde os objetos no heap são separados de acordo com seu tipo, é muito difícil reatribuí-los como um tipo diferente de objeto dentro da janela de corrida.
Os pesquisadores prepararam um exploit funcional que não requer a inclusão de namespaces de identificador de usuário (user namespaces) para sua operação e pode fornecer acesso root ao host quando um usuário sem privilégios inicia o exploit em um contêiner.
“Nossa exploração tem como alvo a versão 5.10.90 do kernel, a versão que o Google estava executando remotamente na época. Tivemos que ajustar nossa exploração às especificações particulares do servidor (4 núcleos Skylake Xeon @ 2.80Ghz, 16GiB de RAM), mas com alguns ajustes, qualquer máquina executando um kernel vulnerável deve ser explorável.”
A exploração também funciona no ambiente nsjail isolado na distribuição do Google COS (Container Optimized OS) baseada no Chromium OS e usada no Google Cloud Platform em máquinas virtuais do Compute Engine.
O exploit foi projetado para funcionar com ramificações do kernel de 5.10 a 5.12. Por fim, vale ressaltar que o problema foi resolvido em abril nas atualizações 5.10.111, 5.15.34 e 5.17.3.