Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

ЛентыКонтактыКонфиденциальность© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2026-98937 — Проверенный PoC и анализ обхода проверки прав в подсистеме perf/core ядра Linux, который приводит к утечке адресов цепочки вызовов ядра непривилегированным задачам Android, что позволяет вычислить смещение KASLR. | Kitploit
Инструменты/GitHubGitHub/woshigenm/cve-2026-98937
Безопасность AndroidПовышение привилегийАнализ уязвимостейЭксплуатацияСбор информацииСтатьи и Исследования
GitHubwoshigenm/cve-2026-98937

CVE-2026-98937

Проверенный PoC и анализ обхода проверки прав в подсистеме perf/core ядра Linux, который приводит к утечке адресов цепочки вызовов ядра непривилегированным задачам Android, что позволяет вычислить смещение KASLR.

Репозиторий
424 дней назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2026-98937 — обход проверки прав доступа к цепочкам вызовов ядра в perf

English | 简体中文

Обход проверки прав доступа в Linux perf/core: непривилегированная задача может запрашивать цепочки вызовов ядра, устанавливая exclude_kernel=1, тем самым обходя проверку perf_allow_kernel() и раскрывая кадры стека ядра через кольцевой буфер perf. Этот репозиторий содержит анализ и проверенный PoC; ошибка приводит к утечке информации, а не к примитиву прямой эскалации привилегий.

Статус

ПунктЗначение
CVECVE-2026-98937
КлассОбход проверки прав доступа / раскрытие информации (CWE-284/CWE-269)
ЦельAndroid arm64 (проверено на HONOR YLP-W00 и Redmi K70)
ЯдроYLP-W00: 6.12.38-android16-5-gfde7767f6ef6-abogki481467632-4k; K70: 5.15.178-android13-8-00021-g6f2f96be86b9-ab13729987
SELinuxEnforcing (u:r:shell:s0)
ИсправленоНет; исправлено в upstream в 6.12.113 / 6.18.56 / 7.2.10 / 7.3+
СтатусPoC проверен; оракул KASLR slide подтверждён на 6.12.38 и 5.15.178
Предварительная проверкаsrc/vuln_precheck.h

Уязвимые версии

Уязвимы ядра до указанного ниже исправления. Исправлено коммитом a4b016d0a29038a5b7c96bf62c054bf7832451d9 ("perf/core: Check kernel access when kernel callchains are requested", Dapeng Mi, объединён 2026-06-30) и соответствующими стабильными бэкпортами.

Корневая причина

perf_event_open() ранее проверял профилирование ядра только по !attr.exclude_kernel:

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

perf_allow_kernel() содержит как проверку perf_event_paranoid > 1, так и хук SELinux perf_event { kernel }. Задача может установить exclude_kernel=1, при этом всё ещё запрашивая цепочки вызовов ядра (PERF_SAMPLE_CALLCHAIN с exclude_callchain_kernel=0); затем perf_callchain() собирает часть ядра независимо от фильтра сэмплирования. События аппаратного PMU, подсчитывающие только пользовательский режим, могут получить своё прерывание переполнения в контексте ядра (skid), поэтому perf_callchain_kernel() разворачивает стек ядра и записывает адреса текста ядра в кольцевой буфер.

Исправление вызывает perf_allow_kernel(), когда запрашивается либо сэмплирование ядра, либо цепочки вызовов ядра:

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

Приведённый выше фрагмент — это форма из стабильного дерева 6.12.113, в которой perf_allow_kernel() больше не принимает указатель на атрибут; в upstream-коммите используется то же условие с perf_allow_kernel(&attr).

Полный путь вызова, механика утечки (skid), данные аудита SELinux и измерения на устройстве см. в docs/analysis.md.

Схема верификации

PoC выполняет три случая как непривилегированный shell-процесс:

СлучайАтрибуты perf_eventОжидаемое поведение на уязвимом ядре
Aexclude_kernel=0EACCES (активен шлюз kernel-perf)
Bexclude_kernel=1, exclude_callchain_kernel=1событие разрешено, нет кадров цепочки вызовов ядра
Cexclude_kernel=1, exclude_callchain_kernel=0событие разрешено, кадры цепочки вызовов ядра раскрыты

На проверенном YLP-W00 (ядро 6.12.38, SELinux Enforcing):

  • Случай A: EACCES, с avc: denied { kernel } ... tclass=perf_event в журнале аудита.
  • Случай B: событие открыто, 0 записей цепочки вызовов ядра.
  • Случай C: событие открыто, ~179 тыс. сэмплов с контекстом ядра и ~537 тыс. адресов цепочки вызовов ядра (3 кадра на сэмпл), все в диапазоне ядра 0xffffffde....

На проверенном Redmi K70 (ядро 5.15.178, сторонняя прошивка Android 17, SELinux Enforcing) наблюдалась та же картина:

  • Случай A: EACCES, та же строка аудита SELinux { kernel }.
  • Случай B: событие открыто, 0 записей цепочки вызовов ядра.
  • Случай C: событие открыто; 14 090 адресов цепочки вызовов ядра в 2 432 сэмплах при периоде 1000 и 5 049 в 876 сэмплах при периоде 5000, в диапазоне ядра 0xffffffdd....

На проверенных устройствах исправленное ядро отклонило бы случай C на perf_event_open() с EACCES, поскольку запрос цепочки вызовов ядра теперь доходит до perf_allow_kernel().

Вывод смещения KASLR

При наличии соответствующего vmlinux утёкшие кадры цепочки вызовов становятся оракулом смещения KASLR для каждой загрузки. Виртуальное смещение на arm64 выровнено по 2 МиБ, и каждый утёкший адрес кода должен удовлетворять _stext <= addr - slide < _etext; пересечение этих интервалов обычно оставляет ровно одно смещение.

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

На проверенной загрузке YLP-W00 6.12.38 три кадра дают уникальное значение slide=0x1DCFC00000 (runtime _text=0xffffffde4fc00000):

Утёкший адресАдрес на этапе компоновкиСимвол
0xffffffde50748c780xffffffc080b48c78local_daif_restore+0x4 (msr DAIF, x0; ret)
0xffffffde50d406e00xffffffc0811406e0el0t_64_sync_handler+0x70 (после bl el0_svc)
0xffffffde4fc115880xffffffc080011588el0t_64_sync+0x1a8 (после bl el0t_64_sync_handler)

Это кадры текста ядра, а не модулей: ожидающее прерывание PMU доставляется ровно на ret после msr DAIF, x0 на пути входа в системный вызов. Сырые адреса нельзя символизировать напрямую при KASLR; сначала вычтите slide. Если кадр является адресом модуля, ни один slide не помещает все адреса в [_stext, _etext), и скрипт сообщает об этом вместо угадывания. Slide меняется при каждой загрузке, и его нельзя кэшировать между перезагрузками.

Redmi K70 (5.15.178) также был проверен. Его соответствующий образ был извлечён из /sdcard/boot.img (boot v4; встроенная строка версии совпадает с работающим ядром), и vmlinux-to-elf восстановил 158 668 символов. Семь уникальных кадров из одного прогона с периодом 1000 дают slide=0x1D93800000 (runtime _text=0xffffffdd9b800000), что соответствует syscall_trace_enter, el0_svc_common, do_el0_svc, el0_svc, el0t_64_sync_handler, el0t_64_sync и syscall_trace_exit.

База на этапе компоновки зависит от ветки — не используйте значение 6.12 на 5.15:

Ветка ядраKIMAGE_VADDR
Android 13-5.15 (K70)0xffffffc008000000
Android 16-6.12 (YLP-W00)0xffffffc080000000
upstream v5.15 (другая раскладка)0xffffffc010000000

vmlinux-to-elf автоматически определил 0xffffffc008000000 для образа K70, что совпадает с AOSP android13-5.15. Если автоматически определённая база ELF отличается от KIMAGE_VADDR ветки, передайте --link-base (или SLIDE_LINK_BASE=): символизация остаётся в пространстве ELF, сообщаемый slide вычисляется относительно истинной базы, а runtime _text инвариантен к сдвигу базы на константу. Подача утечки K70 в образ 6.12.38 остаётся намеренным негативным тестом и не даёт кандидатов.

Сборка

Требования:

  • Android NDK r29 в /opt/android-ndk-r29 (переопределяется через 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

Артефакты записываются в build/ и игнорируются git.

Использование

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

# directly
adb push build/poc /data/local/tmp/poc
adb shell chmod 755 /data/local/tmp/poc
adb shell /data/local/tmp/poc --check
adb shell /data/local/tmp/poc --duration 2 --period 1000

Параметры:

Скачать инструмент