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

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

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

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

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

Категории

Все категории
Loading categories
cve-2023-20768 — Анализ CVE в ядре Android и PoC для type confusion в аллокаторе ION от MediaTek, включая диффинг первопричины, непривилегированный триггер и оценку эксплуатируемости. | Kitploit
Инструменты/GitHubGitHub/murf-xd/cve-2023-20768
Безопасность AndroidАнализ уязвимостейЭксплуатацияОбратная инженерияМобильная безопасностьАнализ Бинарных ФайловЭксплуатация Бинарных Файлов
GitHubmurf-xd/cve-2023-20768

cve-2023-20768

Анализ CVE в ядре Android и PoC для type confusion в аллокаторе ION от MediaTek, включая диффинг первопричины, непривилегированный триггер и оценку эксплуатируемости.

Репозиторий
31 месяц назадЕщё не проверено

Популярное

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

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

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

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

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

CVE-2023-20768 на Samsung Galaxy M32 — исследование достижимости

Резюме. CVE-2023-20768 — это путаница типов (CWE-843) в аллокаторе ION от MediaTek. Я проверил, реально ли она эксплуатируется на Samsung SM-M325F (Galaxy M32, Helio G80) с прошивкой от июля 2022 года. Уязвимый код присутствует, и я доказал, что он выполняется на этом устройстве, когда его запускает непривилегированный процесс. Превратить это в эксплойт мне не удалось. Путь ioctl ограничен проверками ввода, а путь, содержащий настоящее чтение за пределами буфера, обрабатывает только настоящие буферы ION, потому что вторая проверка указателя dma_buf_ops отклоняет всё, что я мог подделать. В этом отчёте описано, как я пришёл к такому выводу, включая один промежуточный вывод, который оказался ошибочным.

Уязвимость публичная и уже закрыта патчем. Все тесты проводились на моём собственном устройстве с root-доступом через Magisk.

Почему именно это устройство

Ошибка находится в коде ION от MediaTek, а не в апстрим-Linux и не в том, что написала Samsung. MediaTek поставляет собственный форк аллокатора Android ION в BSP, который достаётся каждому вендору, делающему устройства на их чипах. В M32 стоит Helio G80, поэтому этот код туда попадает. Тот же телефон с SoC Exynos вообще не был бы затронут.

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

Я вытащил образы vmlinux 2022 (уязвимый) и 2023 (исправленный) и сравнил их в IDA. Изменились две функции ION:

Функция20222023
ion_drv_file_to_bufferstrstr(name, "dmabuf")is_dma_buf_file()
_ion_ioctlstrcmp(name, "ion")is_dma_buf_file()

is_dma_buf_file не существует в образе 2022 года. Она появляется в версии 2023. То есть обе функции определяли, является ли struct file буфером dma_buf, по имени, а исправление заменило это настоящей проверкой типа. Если перепутать объект здесь, ядро читает не-dma_buf так, как будто это dma_buf.

Как добраться до кода из пользовательского пространства

Из этих двух функций _ion_ioctl — та, до которой может добраться непривилегированный процесс:

root@kitploit:~
open("/dev/ion")
  -> ion_ioctl                      (.unlocked_ioctl)
  -> ION_IOC_CUSTOM  (0xC0104906)
  -> ion_custom_ioctl
  -> _ion_ioctl
  -> case 0: ION_SYS_CACHE_SYNC
  -> find_vma(user_VA)              (call site at _ion_ioctl+0x9f0)
  -> strcmp(vma->vm_file...name, "ion")

Запрос — это ion_custom_data { u32 cmd = 0; u64 arg; }, указывающий на 120-байтовую структуру ion_sys_data:

spoof.c формирует такой запрос.

Доказательство диспетчеризации

Я не мог просто трассировать это. Устройство блокирует kprobe_events, set_ftrace_filter и function_graph политикой SELinux от Samsung и усилением ядра, а printk'и ION спрятаны за debug-проверкой, поэтому dmesg молчит.

Поэтому вместо этого я использовал коды возврата как оракул. Четыре запроса — и по тому, что возвращается, видно, куда пошло выполнение:

Успех в случае C означает, что switch действительно диспетчеризует по sys_cmd. Различие между A и B означает, что VA обрабатывается, а это помещает выполнение внутрь find_vma. Это и есть уязвимый путь, достижимый без root.

Где это остановилось

Дойти до проверки — не значит обойти её. Я проверил, что именно принимает strcmp:

  • Настоящий буфер ION, отображённый через ION_IOC_SHARE, а затем mmap, проходит проверку и возвращает 0.
  • memfd с именем memfd:ion не проходит, возвращается -EFAULT.
  • Обычный файл, названный буквально ion, тоже не проходит, возвращается -EFAULT.

Значит, поле, сравниваемое по смещению vm_file+0x60, — это не имя файла. Оно внутреннее для dma_buf, почти наверняка dma_buf->exp_name, которое ION устанавливает в "ion". Проверка некорректна по своей конструкции, но ничто, что я могу создать из пользовательского пространства, не может установить это поле.

Затем я фаззил этот путь: sync_type от 0 до 7, размеры {0, 1, 0x1000, 0x100000, 0xffffffff}, VA {настоящий ion-буфер, memfd, 0} — 120 случаев, плюс проверка с освобождённым handle на предмет use-after-free. Ни одного краха, устройство осталось в строю. Слишком большие размеры отсекаются до find_vma и возвращают 0. sync_type с 3 по 5 попадают в путь m4u и возвращают -EPERM. Всё, что больше 5, возвращает -EINVAL. Освобождённый handle возвращает -EINVAL, то есть ION его валидирует, и UAF здесь нет.

Другая функция и ложный след

Настоящее чтение за пределами буфера находится в ion_drv_file_to_buffer. Она выполняет ldr [private_data+0x28], читая private_data не-dma_buf так, будто это dma_buf. Там есть сравнение ops == &ion_dma_buf_ops (таблица по адресу 0xFFFFFF800A097F18), но оно происходит после этого чтения, поэтому не предотвращает его. Далее по цепочке __do_dump_share_fd читает поля +0x28, +0x48, +0x50, +0xb8, +0xe4 из возвращённого буфера и печатает их, а ldr x8, [buf+0x28]; ldr [x8+0x30] — это разыменование дикого указателя для перепутанного объекта.

Триггер — ion_dump_all_share_fds, которая с помощью iterate_fd обходит файловые дескрипторы каждого процесса-клиента ION. Сначала я заключил, что она запускается только при чтении узла debugfs у ION, а в этом ядре CONFIG_DEBUG_FS не задан. Я проверил это тремя способами: /proc/config.gz, отсутствие debugfs в /proc/filesystems и mount -t debugfs, возвращающий ENODEV. Я списал этот путь как структурно недостижимый.

Это было ошибкой. dump_header — дамп памяти OOM-киллера — содержит прямой вызов bl ion_mm_heap_memory_detail по адресу 0xffffff8008204b9c, а dump_header вызывается из out_of_memory и oom_kill_process. Никакой debugfs не нужен.

memcg_oom.c это подтверждает. Он создаёт cgroup в /dev/memcg, ограничивает и memory.limit_in_bytes, и memory.memsw.limit_in_bytes до 8MB (ограничение только первого позволяет потомку уйти в своп zram), и форкает дочерний процесс, который выделяет память, пока не умрёт. Затем dmesg показывает:

root@kitploit:~
dump_header <- oom_kill_process <- out_of_memory <- mem_cgroup_oom_synchronize

за которым следует полный вывод ion_mm_heap_memory_detail и __do_dump_share_fd, показывающий настоящие dma_buf-буферы gralloc. То есть уязвимая функция выполняется во время события, которое может вызвать любой непривилегированный процесс. Есть и третий триггер — ShowStatus из hang_detect_dump_thread в сторожевом таймере MediaTek.

Почему это всё равно не работает

Я держал 32 memfd с именем memfd:dmabuf и вызвал тот же memcg OOM. Если бы один из моих попал в ion_drv_file_to_buffer, strstr прошла бы, private_data был бы NULL, и ядро напечатало бы [ION]ion_drv_file_to_buffer warnning, dmabuf is NULL с уровнем KERN_ERR. Эта строка ни разу не появилась. В дамп попали только клиенты графики и gralloc. Либо таблица fd обычного клиента /dev/ion — не то, что iterate_fd обходит в этом месте, либо memfd молча отбрасывается ещё до печати.

В любом случае OOM-дамп обрабатывает только легитимные dma_buf-буферы системы, которые проходят проверку без проблем. К тому же memfd — единственный тип fd, имя которого я могу контролировать настолько, чтобы оно содержало «dmabuf», а он не может вызвать сбой.

Вердикт

Уязвимость присутствует. Уязвимый код достижим и реально выполняется в этой сборке, запускается без root. Превратить его в эксплойт из пользовательского пространства здесь нельзя. Путь ioctl ограничен валидацией handle, проверкой размера и access_ok. Путь дампа видит только настоящие буферы ION, а подделка блокируется проверкой ops == &ion_dma_buf_ops. Чтобы продвинуться дальше, нужен контролируемый не-ION объект, у которого exp_name равен "ion", либо другой примитив вроде UAF в буфере ION или гонка TOCTOU.

Файлы

  • spoof.c — PoC для cache-sync ioctl и дифференциальный оракул
  • memcg_oom.c — memcg OOM-триггер для пути дампа
  • trigger.c, oom_trigger.c — более ранние попытки триггеров
  • boot_images/ — извлечённые образы ядра (2022 и 2023) и база IDA для сборки 2022 года
Скачать инструмент
СмещениеПоле
+0x00sys_cmd = 0
+0x08ion handle (сначала выделите его, подойдёт heap_id_mask = 0x1)
+0x10пользовательский виртуальный адрес
+0x18младшая половина = размер, старшая половина = sync_type из {0,1,2}
СлучайЗапросРезультат
Asys_cmd=0, поддельный VA-EFAULT
Bsys_cmd=0, VA = 00
Csys_cmd=40
Dsys_cmd=99-EFAULT