Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-98937 — PoC vérifié et analyse d'un contournement de vérification de permissions dans perf/core sous Linux, qui divulgue des adresses de chaîne d'appels du noyau à des tâches Android non privilégiées, permettant ainsi de dériver le décalage KASLR. | Kitploit
Outils/GitHubGitHub/woshigenm/cve-2026-98937
Sécurité AndroidEscalade de PrivilègesAnalyse des VulnérabilitésExploitationCollecte d'InformationsArticles et Recherche
GitHubwoshigenm/cve-2026-98937

CVE-2026-98937

PoC vérifié et analyse d'un contournement de vérification de permissions dans perf/core sous Linux, qui divulgue des adresses de chaîne d'appels du noyau à des tâches Android non privilégiées, permettant ainsi de dériver le décalage KASLR.

Voir le dépôt
42il y a 4 joursPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2026-98937 — contournement des permissions de callchain du noyau perf

English | 简体中文

Contournement de la vérification de permissions dans perf/core de Linux : une tâche non privilégiée peut demander des callchains du noyau tout en définissant exclude_kernel=1, contournant ainsi le contrôle perf_allow_kernel() et divulguant des frames de pile du noyau via le tampon circulaire perf. Ce dépôt contient l'analyse et un PoC vérifié ; la faille permet une fuite d'informations, et non une primitive d'élévation de privilèges directe.

Statut

ÉlémentValeur
CVECVE-2026-98937
ClasseContournement de permissions / divulgation d'informations (CWE-284/CWE-269)
CibleAndroid arm64 (vérifié sur HONOR YLP-W00 et Redmi K70)
NoyauYLP-W00 : 6.12.38-android16-5-gfde7767f6ef6-abogki481467632-4k ; K70 : 5.15.178-android13-8-00021-g6f2f96be86b9-ab13729987
SELinuxEnforcing (u:r:shell:s0)
CorrigéNon ; corrigé en amont dans 6.12.113 / 6.18.56 / 7.2.10 / 7.3+
StatutPoC vérifié ; oracle de décalage KASLR validé sur 6.12.38 et 5.15.178
Pré-vérificationsrc/vuln_precheck.h

Versions affectées

Les noyaux antérieurs au correctif ci-dessous sont affectés. Corrigé par a4b016d0a29038a5b7c96bf62c054bf7832451d9 ("perf/core: Check kernel access when kernel callchains are requested", Dapeng Mi, fusionné le 2026-06-30) et les rétroportages stables correspondants.

Cause racine

perf_event_open() ne conditionnait auparavant le profilage du noyau qu'à !attr.exclude_kernel :

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

perf_allow_kernel() contient à la fois la vérification perf_event_paranoid > 1 et le hook SELinux perf_event { kernel }. Une tâche peut définir exclude_kernel=1 tout en demandant encore des callchains noyau (PERF_SAMPLE_CALLCHAIN avec exclude_callchain_kernel=0) ; perf_callchain() collecte alors la partie noyau indépendamment du filtre d'échantillonnage. Les événements PMU matériels ne comptant que le mode utilisateur peuvent déclencher leur interruption de débordement en contexte noyau (skid), de sorte que perf_callchain_kernel() déroule la pile noyau et écrit des adresses de texte noyau dans le tampon circulaire.

Le correctif appelle perf_allow_kernel() lorsque l'échantillonnage noyau ou les callchains noyau sont demandés :

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

Le snippet ci-dessus est la forme de la branche stable 6.12.113, dans laquelle perf_allow_kernel() ne prend plus de pointeur d'attribut ; le commit amont utilise la même condition avec perf_allow_kernel(&attr).

Voir docs/analysis.md pour le chemin d'appel complet, la mécanique du skid, les preuves d'audit SELinux et les mesures sur appareil.

Conception de la vérification

Le PoC exécute trois cas en tant que processus shell non privilégié :

Casattributs perf_eventAttendu sur un noyau vulnérable
Aexclude_kernel=0EACCES (filtre kernel-perf actif)
Bexclude_kernel=1, exclude_callchain_kernel=1événement autorisé, aucune frame de callchain noyau
Cexclude_kernel=1, exclude_callchain_kernel=0événement autorisé, frames de callchain noyau divulguées

Sur le YLP-W00 vérifié (noyau 6.12.38, SELinux Enforcing) :

  • Cas A : EACCES, avec avc: denied { kernel } ... tclass=perf_event dans le journal d'audit.
  • Cas B : événement ouvert, 0 entrée de callchain noyau.
  • Cas C : événement ouvert, ~179k échantillons avec contexte noyau et ~537k adresses de callchain noyau (3 frames par échantillon), toutes dans la plage noyau 0xffffffde....

Sur le Redmi K70 vérifié (noyau 5.15.178, ROM Android 17 tierce, SELinux Enforcing), le même schéma a été observé :

  • Cas A : EACCES, même ligne d'audit SELinux { kernel }.
  • Cas B : événement ouvert, 0 entrée de callchain noyau.
  • Cas C : événement ouvert ; 14 090 adresses de callchain noyau dans 2 432 échantillons à période 1000, et 5 049 dans 876 échantillons à période 5000, dans la plage noyau 0xffffffdd....

Sur les appareils vérifiés, un noyau corrigé rejetterait le cas C au niveau de perf_event_open() avec EACCES, car la requête de callchain noyau atteint désormais perf_allow_kernel().

Dérivation du décalage KASLR

Avec un vmlinux correspondant, les frames de callchain divulguées deviennent un oracle de décalage KASLR par démarrage. Le décalage virtuel arm64 est aligné sur 2 MiB, et chaque adresse de texte divulguée doit satisfaire _stext <= addr - slide < _etext ; l'intersection de ces intervalles ne laisse normalement qu'un seul décalage.

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

Sur le boot YLP-W00 6.12.38 vérifié, trois frames donnent le slide=0x1DCFC00000 unique (runtime _text=0xffffffde4fc00000) :

Adresse fuitéeAdresse au link-timeSymbole
0xffffffde50748c780xffffffc080b48c78local_daif_restore+0x4 (msr DAIF, x0; ret)
0xffffffde50d406e00xffffffc0811406e0el0t_64_sync_handler+0x70 (après bl el0_svc)
0xffffffde4fc115880xffffffc080011588el0t_64_sync+0x1a8 (après bl el0t_64_sync_handler)

Ce sont des frames de texte du noyau principal, pas des modules : l'interruption PMU en attente est délivrée exactement au ret après msr DAIF, x0 dans le chemin d'entrée d'appel système. Les adresses brutes ne peuvent pas être symbolisées directement sous KASLR ; il faut d'abord soustraire le slide. Si une frame est une adresse de module, aucun slide ne place toutes les adresses dans [_stext, _etext) et le script le signale au lieu de deviner. Le slide change à chaque boot et ne doit pas être mis en cache entre reboots.

Le Redmi K70 (5.15.178) a également été validé. Son image correspondante a été extraite de /sdcard/boot.img (boot v4 ; la chaîne de version intégrée correspond au noyau en cours d'exécution) et vmlinux-to-elf a récupéré 158 668 symboles. Sept frames uniques issues d'une exécution de période 1000 donnent slide=0x1D93800000 (runtime _text=0xffffffdd9b800000), correspondant à syscall_trace_enter, el0_svc_common, do_el0_svc, el0_svc, el0t_64_sync_handler, el0t_64_sync et syscall_trace_exit.

La base au link-time est spécifique à la branche — ne réutilisez pas la valeur 6.12 sur 5.15 :

Branche du noyauKIMAGE_VADDR
Android 13-5.15 (K70)0xffffffc008000000
Android 16-6.12 (YLP-W00)0xffffffc080000000
upstream v5.15 (disposition différente)0xffffffc010000000

vmlinux-to-elf a auto-détecté 0xffffffc008000000 pour l'image du K70, correspondant à AOSP android13-5.15. Si la base ELF auto-détectée diffère du KIMAGE_VADDR de la branche, passez --link-base (ou SLIDE_LINK_BASE=) : la symbolisation reste dans l'espace ELF, le slide rapporté est rendu relatif à la vraie base, et le _text runtime est invariant à un décalage constant de la base. Fournir la fuite du K70 à l'image 6.12.38 reste un test négatif délibéré et ne produit aucun candidat.

Build

Prérequis :

  • Android NDK r29 dans /opt/android-ndk-r29 (remplaçable avec 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

Les artefacts sont écrits dans build/ et sont ignorés par git.

Utilisation

Télécharger l’outil