Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2026-98937 — PoC verificado y análisis de un bypass de comprobación de permisos en perf/core de Linux que filtra direcciones de la cadena de llamadas del kernel a tareas de Android sin privilegios, lo que permite derivar el desplazamiento de KASLR. | Kitploit
Herramientas/GitHubGitHub/woshigenm/cve-2026-98937
Seguridad AndroidEscalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónRecopilación de InformaciónPapers e Investigación
GitHubwoshigenm/cve-2026-98937

CVE-2026-98937

PoC verificado y análisis de un bypass de comprobación de permisos en perf/core de Linux que filtra direcciones de la cadena de llamadas del kernel a tareas de Android sin privilegios, lo que permite derivar el desplazamiento de KASLR.

Ver Repositorio
42hace 4 díasAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2026-98937 — omisión de permisos en callchain del kernel de perf

English | 简体中文

Omisión de la comprobación de permisos en perf/core de Linux: una tarea sin privilegios puede solicitar callchains del kernel mientras establece exclude_kernel=1, saltándose la barrera perf_allow_kernel() y divulgando marcos de pila del kernel a través del ring buffer de perf. Este repositorio contiene el análisis y un PoC verificado; el fallo produce una fuga de información, no una primitiva directa de escalada de privilegios.

Estado

ElementoValor
CVECVE-2026-98937
ClaseOmisión de permisos / divulgación de información (CWE-284/CWE-269)
ObjetivoAndroid arm64 (verificado en HONOR YLP-W00 y 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)
ParcheadoNo; corregido upstream en 6.12.113 / 6.18.56 / 7.2.10 / 7.3+
EstadoPoC verificado; oráculo de desplazamiento KASLR validado en 6.12.38 y 5.15.178
Comprobación previasrc/vuln_precheck.h

Versiones afectadas

Los kernels anteriores a la corrección indicada a continuación están afectados. Corregido por a4b016d0a29038a5b7c96bf62c054bf7832451d9 ("perf/core: Check kernel access when kernel callchains are requested", Dapeng Mi, fusionado el 2026-06-30) y los backports estables correspondientes.

Causa raíz

perf_event_open() solía controlar el perfilado del kernel únicamente mediante !attr.exclude_kernel:

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

perf_allow_kernel() contiene tanto la comprobación perf_event_paranoid > 1 como el hook de SELinux perf_event { kernel }. Una tarea puede establecer exclude_kernel=1 mientras sigue solicitando callchains del kernel (PERF_SAMPLE_CALLCHAIN con exclude_callchain_kernel=0); perf_callchain() entonces recopila la parte del kernel de forma independiente al filtro de muestreo. Los eventos de PMU de hardware que cuentan solo el modo usuario pueden tomar su interrupción de desbordamiento en contexto de kernel (skid), por lo que perf_callchain_kernel() desenrolla la pila del kernel y escribe direcciones de texto del kernel en el ring buffer.

La corrección llama a perf_allow_kernel() cuando se solicita muestreo del kernel o callchains del kernel:

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

El fragmento anterior es la forma del árbol estable 6.12.113, en la que perf_allow_kernel() ya no recibe un puntero de atributo; el commit upstream usa la misma condición con perf_allow_kernel(&attr).

Consulte docs/analysis.md para ver la ruta de llamada completa, la mecánica del skid, la evidencia de auditoría de SELinux y las mediciones del dispositivo.

Diseño de verificación

El PoC ejecuta tres casos como un proceso de shell sin privilegios:

Casoatributos de perf_eventEsperado en un kernel vulnerable
Aexclude_kernel=0EACCES (puerta de kernel-perf activa)
Bexclude_kernel=1, exclude_callchain_kernel=1evento permitido, sin frames de callchain del kernel
Cexclude_kernel=1, exclude_callchain_kernel=0evento permitido, frames de callchain del kernel divulgados

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

  • Caso A: EACCES, con avc: denied { kernel } ... tclass=perf_event en el registro de auditoría.
  • Caso B: evento abierto, 0 entradas de callchain del kernel.
  • Caso C: evento abierto, ~179k muestras con contexto de kernel y ~537k direcciones de callchain del kernel (3 frames por muestra), todas en el rango de kernel 0xffffffde....

En el Redmi K70 verificado (kernel 5.15.178, ROM Android 17 de terceros, SELinux Enforcing), se observó el mismo patrón:

  • Caso A: EACCES, la misma línea de auditoría de SELinux { kernel }.
  • Caso B: evento abierto, 0 entradas de callchain del kernel.
  • Caso C: evento abierto; 14.090 direcciones de callchain del kernel en 2.432 muestras con período 1000, y 5.049 en 876 muestras con período 5000, en el rango de kernel 0xffffffdd....

En los dispositivos verificados, un kernel corregido rechazaría el caso C en perf_event_open() con EACCES porque la solicitud de callchain del kernel ahora llega a perf_allow_kernel().

Derivación del slide de KASLR

Con un vmlinux coincidente, los frames de callchain filtrados se convierten en un oráculo del slide de KASLR por arranque. El slide virtual de arm64 está alineado a 2 MiB, y cada dirección de texto filtrada debe satisfacer _stext <= addr - slide < _etext; la intersección de esos intervalos normalmente deja exactamente un 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

En el arranque verificado YLP-W00 6.12.38, tres frames dan el único slide=0x1DCFC00000 (en tiempo de ejecución _text=0xffffffde4fc00000):

Dirección filtradaDirección en tiempo de enlaceSímbolo
0xffffffde50748c780xffffffc080b48c78local_daif_restore+0x4 (msr DAIF, x0; ret)
0xffffffde50d406e00xffffffc0811406e0el0t_64_sync_handler+0x70 (después de bl el0_svc)
0xffffffde4fc115880xffffffc080011588el0t_64_sync+0x1a8 (después de bl el0t_64_sync_handler)

Estos son frames del texto del núcleo, no de módulos: la interrupción PMU pendiente se entrega exactamente en el ret posterior a msr DAIF, x0 en la ruta de entrada de la llamada al sistema. Las direcciones sin procesar no pueden simbolizarse directamente bajo KASLR; primero hay que restar el slide. Si un frame es una dirección de módulo, ningún slide coloca todas las direcciones en [_stext, _etext) y el script lo informa en lugar de adivinar. El slide cambia en cada arranque y no debe almacenarse en caché entre reinicios.

El Redmi K70 (5.15.178) también ha sido validado. Su imagen correspondiente se extrajo de /sdcard/boot.img (boot v4; la cadena de versión incrustada coincide con el núcleo en ejecución) y vmlinux-to-elf recuperó 158.668 símbolos. Siete frames únicos de una ejecución con período 1000 dan slide=0x1D93800000 (en tiempo de ejecución _text=0xffffffdd9b800000), que se asignan a syscall_trace_enter, el0_svc_common, do_el0_svc, el0_svc, el0t_64_sync_handler, el0t_64_sync y syscall_trace_exit.

La base en tiempo de enlace es específica de cada rama — no reutilices el valor de 6.12 en 5.15:

Rama del núcleoKIMAGE_VADDR
Android 13-5.15 (K70)0xffffffc008000000
Android 16-6.12 (YLP-W00)0xffffffc080000000
upstream v5.15 (disposición diferente)0xffffffc010000000

vmlinux-to-elf detectó automáticamente 0xffffffc008000000 para la imagen del K70, coincidiendo con AOSP android13-5.15. Si la base ELF detectada automáticamente difiere del KIMAGE_VADDR de la rama, pasa --link-base (o SLIDE_LINK_BASE=): la simbolización permanece en el espacio ELF, el slide informado se hace relativo a la base verdadera, y el _text en tiempo de ejecución es invariante ante un desplazamiento constante de la base. Alimentar la filtración del K70 a la imagen 6.12.38 sigue siendo una prueba negativa deliberada y no produce ningún candidato.

Compilación

Requisitos:

  • Android NDK r29 en /opt/android-ndk-r29 (sobrescribir con NDK=)
  • GNU make
  • adb
Descargar herramienta