Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-98937 — PoC verificado e análise de um bypass de verificação de permissão no perf/core do Linux que vaza endereços de callchain do kernel para tarefas Android sem privilégios, permitindo a derivação do slide do KASLR. | Kitploit
Ferramentas/GitHubGitHub/woshigenm/cve-2026-98937
Segurança AndroidEscalada de PrivilégiosAnálise de VulnerabilidadesExploraçãoColeta de InformaçõesPapers e Pesquisa
GitHubwoshigenm/cve-2026-98937

CVE-2026-98937

PoC verificado e análise de um bypass de verificação de permissão no perf/core do Linux que vaza endereços de callchain do kernel para tarefas Android sem privilégios, permitindo a derivação do slide do KASLR.

Ver Repositório
42há 4 diasAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2026-98937 — bypass de permissão de callchain do kernel no perf

Português | 简体中文

Bypass da verificação de permissão no perf/core do Linux: uma tarefa sem privilégios pode solicitar callchains do kernel enquanto define exclude_kernel=1, ignorando a barreira perf_allow_kernel() e divulgando frames de pilha do kernel através do ring buffer do perf. Este repositório contém a análise e um PoC verificado; o bug proporciona um vazamento de informações, não uma primitiva direta de escalada de privilégios.

Status

ItemValor
CVECVE-2026-98937
ClasseBypass de permissão / divulgação de informações (CWE-284/CWE-269)
AlvoAndroid arm64 (verificado em HONOR YLP-W00 e Redmi K70)
KernelYLP-W00: 6.12.38-android16-5-gfde7767f6ef6-abogki481467632-4k; K70: 5.15.178-android13-8-00021-g6f2f96be86b9-ab13729987
SELinuxEnforcing (u:r:shell:s0)
CorrigidoNão; corrigido upstream em 6.12.113 / 6.18.56 / 7.2.10 / 7.3+
StatusPoC verificado; oráculo de KASLR slide validado em 6.12.38 e 5.15.178
Pré-verificaçãosrc/vuln_precheck.h

Versões afetadas

Kernels anteriores à correção abaixo são afetados. Corrigido por a4b016d0a29038a5b7c96bf62c054bf7832451d9 ("perf/core: Check kernel access when kernel callchains are requested", Dapeng Mi, mesclado em 2026-06-30) e os backports estáveis correspondentes.

Causa raiz

perf_event_open() costumava restringir a criação de perfis do kernel apenas com base em !attr.exclude_kernel:

if (!attr.exclude_kernel) {
        err = perf_allow_kernel(&attr);
        if (err)
                return err;
}

perf_allow_kernel() contém tanto a verificação perf_event_paranoid > 1 quanto o hook SELinux perf_event { kernel }. Uma tarefa pode definir exclude_kernel=1 enquanto ainda solicita callchains do kernel (PERF_SAMPLE_CALLCHAIN com exclude_callchain_kernel=0); perf_callchain() então coleta a parte do kernel independentemente do filtro de amostragem. Eventos de PMU de hardware que contam apenas o modo usuário podem ter sua interrupção de overflow no contexto do kernel (skid), então perf_callchain_kernel() desenrola a pilha do kernel e grava endereços de texto do kernel no ring buffer.

A correção chama perf_allow_kernel() quando amostragem do kernel ou callchains do kernel são solicitadas:

if (!attr.exclude_kernel ||
    ((attr.sample_type & PERF_SAMPLE_CALLCHAIN) &&
     !attr.exclude_callchain_kernel)) {
        err = perf_allow_kernel();
        if (err)
                return err;
}

O trecho acima é a forma da árvore estável 6.12.113, na qual perf_allow_kernel() não recebe mais um ponteiro de atributo; o commit upstream usa a mesma condição com perf_allow_kernel(&attr).

Consulte docs/analysis.md para o caminho de chamada completo, a mecânica do skid, as evidências de auditoria do SELinux e as medições do dispositivo.

Design de verificação

O PoC executa três casos como um processo de shell sem privilégios:

Casoatributos de perf_eventEsperado em um kernel vulnerável
Aexclude_kernel=0EACCES (gate de kernel-perf ativo)
Bexclude_kernel=1, exclude_callchain_kernel=1evento permitido, sem frames de callchain do kernel
Cexclude_kernel=1, exclude_callchain_kernel=0evento permitido, frames de callchain do kernel divulgados

No YLP-W00 verificado (kernel 6.12.38, SELinux Enforcing):

  • Caso A: EACCES, com avc: denied { kernel } ... tclass=perf_event no log de auditoria.
  • Caso B: evento aberto, 0 entradas de callchain do kernel.
  • Caso C: evento aberto, ~179k amostras com contexto de kernel e ~537k endereços de callchain do kernel (3 frames por amostra), todos no intervalo de kernel 0xffffffde....

No Redmi K70 verificado (kernel 5.15.178, ROM Android 17 de terceiros, SELinux Enforcing), o mesmo padrão foi observado:

  • Caso A: EACCES, mesma linha de auditoria SELinux { kernel }.
  • Caso B: evento aberto, 0 entradas de callchain do kernel.
  • Caso C: evento aberto; 14.090 endereços de callchain do kernel em 2.432 amostras com período 1000, e 5.049 em 876 amostras com período 5000, no intervalo de kernel 0xffffffdd....

Nos dispositivos verificados, um kernel corrigido rejeitaria o caso C em perf_event_open() com EACCES porque a solicitação de callchain do kernel agora chega a perf_allow_kernel().

Derivação do slide KASLR

Com um vmlinux correspondente, os frames de callchain vazados tornam-se um oráculo de slide KASLR por boot. O slide virtual arm64 é alinhado a 2 MiB, e todo endereço de texto vazado deve satisfazer _stext <= addr - slide < _etext; a interseção desses intervalos normalmente deixa exatamente um slide.

make slide \
  SLIDE_VMLINUX=/path/to/vmlinux-6.12.38.elf \
  SLIDE_LINK_BASE=0xffffffc080000000 \
  SLIDE_LOG=logs/poc-ylp-w00-20261027-020133-period1000.log

No boot verificado YLP-W00 6.12.38, três frames fornecem o único slide=0x1DCFC00000 (runtime _text=0xffffffde4fc00000):

Endereço vazadoEndereço em tempo de linkSímbolo
0xffffffde50748c780xffffffc080b48c78local_daif_restore+0x4 (msr DAIF, x0; ret)
0xffffffde50d406e00xffffffc0811406e0el0t_64_sync_handler+0x70 (após bl el0_svc)
0xffffffde4fc115880xffffffc080011588el0t_64_sync+0x1a8 (após bl el0t_64_sync_handler)

Estes são frames de texto do kernel principal, não módulos: a interrupção PMU pendente é entregue exatamente no ret após msr DAIF, x0 no caminho de entrada da syscall. Endereços brutos não podem ser simbolizados diretamente sob KASLR; subtraia o slide primeiro. Se um frame for um endereço de módulo, nenhum slide coloca todos os endereços em [_stext, _etext) e o script reporta isso em vez de adivinhar. O slide muda a cada boot e não deve ser armazenado em cache entre reinicializações.

O Redmi K70 (5.15.178) também foi validado. Sua imagem correspondente foi extraída de /sdcard/boot.img (boot v4; a string de versão embutida corresponde ao kernel em execução) e o vmlinux-to-elf recuperou 158.668 símbolos. Sete frames únicos de uma execução com período 1000 fornecem slide=0x1D93800000 (runtime _text=0xffffffdd9b800000), mapeando para syscall_trace_enter, el0_svc_common, do_el0_svc, el0_svc, el0t_64_sync_handler, el0t_64_sync e syscall_trace_exit.

A base em tempo de link é específica do branch — não reutilize o valor de 6.12 no 5.15:

Branch do kernelKIMAGE_VADDR
Android 13-5.15 (K70)0xffffffc008000000
Android 16-6.12 (YLP-W00)0xffffffc080000000
upstream v5.15 (layout diferente)0xffffffc010000000

O vmlinux-to-elf detectou automaticamente 0xffffffc008000000 para a imagem do K70, correspondendo ao AOSP android13-5.15. Se a base ELF detectada automaticamente diferir do KIMAGE_VADDR do branch, passe --link-base (ou SLIDE_LINK_BASE=): a simbolização permanece no espaço ELF, o slide reportado é tornado relativo à base verdadeira, e o _text em runtime é invariante a um deslocamento constante da base. Alimentar o vazamento do K70 na imagem 6.12.38 continua sendo um teste negativo deliberado e não produz nenhum candidato.

Build

Requisitos:

  • Android NDK r29 em /opt/android-ndk-r29 (substitua com NDK=)
  • GNU make
  • adb
make                 # PoC, arm64, API 24
make ARCH=arm API=29 # other ABI / API level
make host            # static build for qemu-aarch64
make emu             # build and run the static PoC locally
make help

Os artefatos são gravados em build/ e são ignorados pelo git.

Uso

make check                         # push + read-only environment pre-check
make run                           # push + full three-case verification
Baixar ferramenta