
Exploit de kernel do Android 14 para Pixel7/8 Pro
Este artigo fornece uma análise aprofundada de duas vulnerabilidades do kernel na GPU Mali, acessíveis a partir da sandbox padrão de aplicativos, que identifiquei e reportei de forma independente ao Google. Inclui um exploit do kernel que alcança capacidades de leitura/escrita arbitrárias do kernel. Consequentemente, desabilita o SELinux e eleva privilégios para root nos modelos Google Pixel 7 e 8 Pro executando as seguintes versões do Android 14:
google/husky/husky:14/UD1A.231105.004/11010374:user/release-keysgoogle/cheetah/cheetah:14/UP1A.231105.003/11010452:user/release-keysgoogle/cheetah/cheetah:14/UP1A.231005.007/10754064:user/release-keysgoogle/panther/panther:14/UP1A.231105.003/11010452:user/release-keys (por m4b4 (Marcel))Este exploit aproveita duas vulnerabilidades: um estouro de inteiro resultante de um patch incompleto no comando ioctl gpu_pixel_handle_buffer_liveness_update_ioctl, e um vazamento de informações nos buffers de mensagens do fluxo da timeline.
Google abordou um estouro de inteiro no comando ioctl gpu_pixel_handle_buffer_liveness_update_ioctl neste commit. Inicialmente, quando reportei este problema, pensei que o bug era causado por um problema no patch descrito anteriormente. Após revisar o relatório, percebi que minha análise da vulnerabilidade estava incorreta. Apesar da minha suposição inicial de que o patch estava incompleto, ele efetivamente resolve e previne um underflow no cálculo. Isso me levou a suspeitar que a alteração não foi aplicada nas compilações de produção. No entanto, embora eu possa causar um underflow no cálculo, não é possível causar um overflow. Isso sugere que o comando ioctl foi parcialmente corrigido, embora não com o patch mostrado acima. Analisando o IDA revelou que outro patch incompleto foi enviado nas versões de produção, e este patch não está presente em nenhum branch git do módulo do kernel da GPU Mali.
Esta vulnerabilidade foi descoberta pela primeira vez na versão mais recente do Android e reportada em 19 de novembro de 2023. O Google posteriormente me informou que já a havia identificado internamente e atribuído CVE-2023-48409 no Boletim de Segurança do Android de dezembro, rotulando-a como uma duplicata.
Embora eu tenha conseguido verificar que o bug foi identificado internamente meses antes do meu relatório (com base na data do commit por volta de 30 de agosto), ainda há confusão. Especificamente, é estranho que os Níveis de Patch de Segurança (SPL) de outubro e novembro dos dispositivos mais recentes ainda estivessem afetados por esta vulnerabilidade — não investiguei versões anteriores a essas. Portanto, não consigo determinar conclusivamente se isso foi realmente uma duplicata e se o patch apropriado estava de fato agendado para dezembro antes da minha submissão, ou se houve uma falha na correção desta vulnerabilidade.
De qualquer forma, o que torna este bug poderoso é o seguinte:
info.live_ranges é totalmente controlado pelo usuário.info.live_ranges possa estar em um deslocamento arbitrário anterior ao início do endereço do kernel buff.Esta vulnerabilidade compartilha semelhanças com a vulnerabilidade de Buffer underflow em DeCxt::RasterizeScaleBiasData() que encontrei e explorei no kernel do iOS 15 em 2022.
A GPU Mali implementa um timeline stream personalizado projetado para coletar informações, serializá-las e subsequentemente escrevê-las em um buffer circular seguindo um formato específico. Os usuários podem invocar o comando ioctl kbase_api_tlstream_acquire para obter um descritor de arquivo, permitindo-lhes ler deste buffer circular. O formato das mensagens é o seguinte:
Por exemplo, a função __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_fence_wait serializa os ponteiros do kernel kbase_kcpu_command_queue e dma_fence no buffer de mensagens, resultando no vazamento de ponteiros do kernel para o processo de espaço do usuário.```c
void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_fence_wait(
struct kbase_tlstream *stream,
const void *kcpu_queue,
const void *fence
)
{
const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_WAIT;
const size_t msg_size = sizeof(msg_id) + sizeof(u64)
+ sizeof(kcpu_queue)
+ sizeof(fence)
;
char *buffer;
unsigned long acq_flags;
size_t pos = 0;
buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags);
pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id));
pos = kbasep_serialize_timestamp(buffer, pos);
pos = kbasep_serialize_bytes(buffer,
pos, &kcpu_queue, sizeof(kcpu_queue));
pos = kbasep_serialize_bytes(buffer,
pos, &fence, sizeof(fence));
kbase_tlstream_msgbuf_release(stream, acq_flags);
}
A prova de conceito do exploit vaza o endereço do objeto `kbase_kcpu_command_queue` monitorando o ID da mensagem `KBASE_TL_KBASE_NEW_KCPUQUEUE`, que é despachado pela função `kbasep_kcpu_queue_new` sempre que um novo objeto de fila kcpu é alocado.
O Google me informou que a vulnerabilidade foi reportada em março de 2023 e recebeu o identificador [CVE-2023-26083](https://source.android.com/docs/security/bulletin/2023-07-01) em seu boletim de segurança. No entanto, consegui reproduzir o problema nos dispositivos Pixel mais recentes com os Pacotes de Nível de Segurança (SPL) de outubro e novembro, indicando que a correção não foi aplicada corretamente ou não foi aplicada. Posteriormente, o Google corrigiu rapidamente o problema no Boletim de Atualização de Segurança de dezembro sem dar créditos, e depois me informou que o problema foi considerado duplicado. A justificativa para rotular este problema como duplicado, no entanto, permanece questionável.
## Exploração
---
Então, tenho duas vulnerabilidades interessantes. A primeira oferece uma capacidade poderosa de modificar o conteúdo de qualquer endereço do kernel alinhado a 16 bytes que venha antes do endereço do ~buff~ alocado. A segunda vulnerabilidade fornece pistas sobre as possíveis localizações de objetos na memória do kernel.