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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2022-22629 — Доказательство концепции для CVE-2022-22629, переполнение буфера в куче в расширении multi-draw WebGL в Safari, с анализом уязвимости и шагами воспроизведения сбоя. | Kitploit
Инструменты/GitHubGitHub/lck0/cve-2022-22629
Анализ уязвимостейЭксплуатацияВеб-безопасность
GitHublck0/cve-2022-22629

CVE-2022-22629

Доказательство концепции для CVE-2022-22629, переполнение буфера в куче в расширении multi-draw WebGL в Safari, с анализом уязвимости и шагами воспроизведения сбоя.

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

Популярное

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

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

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

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

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

CVE-2022-22629 Доказательство концепции

Этот пост о PoC для бага WebGL, который был исправлен в обновлениях безопасности Safari 15.4.

bug

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

https://webglfundamentals.org/webgl/lessons/webgl-how-it-works.html

Этот PoC не о том, как получить примитивы для эксплуатации этого бага, мы просто обсудим анализ уязвимости и как вызвать сбой веб-контента : )

Введение

WebGL — это JavaScript API, используемый в браузерах для рендеринга 2D и 3D графики. Он использует компонент ANGLE в качестве основного бэкенда WebGL, что значительно улучшает совместимость с другими браузерами и обеспечивает соответствие WebGL 2.0 в WebKit. WebGL предлагает множество расширений для разработчика, чтобы выполнять рендеринг с оптимизациями. Итак, мы рассмотрим расширение, которое нас интересует.

Расширения в WebGL

extension

Вы можете прочитать более подробно о расширениях здесь:

https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Using_Extensions

В любом случае, давайте перейдем к багу :)

Анализ уязвимости

Расширение WEBGL_multi_draw

Расширение WEBGL_multi_draw является частью WebGL API и позволяет отрисовывать более одного примитива за один вызов функции. Это может улучшить производительность приложения WebGL, так как снижает затраты на привязку в рендерере и ускоряет время работы потока GPU с однородными данными.

Это расширение предоставляет варианты вызова отрисовки Multi* в функциональности EXT_multi_draw_arrays в дополнение к встроенной переменной вершинного шейдера gl_DrawID, предоставляемой ARB_shader_draw_parameters для OpenGL.

Эти функции ведут себя идентично стандартным функциям DrawArrays() и DrawElements(), за исключением того, что они обрабатывают несколько списков вершин за один вызов. Их основная цель — позволить одному вызову функции отрисовывать более одного примитива, такого как треугольная полоса, треугольный веер и т.д.

Кроме того, это расширение добавляет дополнительную встроенную переменную gl_DrawID в язык шейдеров. Эта переменная содержит индекс отрисовки, который в данный момент обрабатывается вариантом Multi* команды рисования.

https://github.com/WebKit/WebKit/blob/a7f8eacef337cb6691dca0b742d00f80d4f3dd0f/Source/ThirdParty/ANGLE/extensions/ANGLE_multi_draw.txt

Вы можете прочитать более подробно о расширении здесь:

https://registry.khronos.org/webgl/extensions/WEBGL_multi_draw/

Это расширение похоже на API WebGL WebGLRenderingContext.drawArrays() и WebGLRenderingContext.drawElements() и т.д., которые отрисовывают примитивы из данных массивов. Единственное отличие в том, что с помощью этого расширения можно отрисовывать, используя несколько массивов.

Мы можем выполнять эти операции с помощью данного расширения: [1]

  1. ext.multiDrawArraysWEBGL() отрисовывает несколько примитивов из данных массивов (идентично множественным вызовам drawArrays).

  2. ext.multiDrawElementsWEBGL() отрисовывает несколько примитивов из данных массивов элементов (идентично множественным вызовам drawElements).

  3. ext.multiDrawArraysInstancedWEBGL() отрисовывает несколько примитивов из данных массивов (идентично множественным вызовам drawArraysInstanced).

  4. ext.multiDrawElementsInstancedWEBGL() отрисовывает несколько примитивов из данных массивов элементов (идентично множественным вызовам drawElementsInstanced).

Патч

patch

https://github.com/WebKit/WebKit/commit/c087ca07c9125093ca62e8e44024b738bb7d46dc

Уязвимость существует только в Safari 15.0–15.3, потому что это расширение поддерживается только в Safari 15 (iOS) в случае Apple.

Патч очень легко понять, и в нем четко указано, что это переполнение буфера в куче при рендеринге. Эта функция вызывается здесь в WebGLMultiDraw.cpp во всех операциях, которые мы упомянули выше [1]. Давайте разберемся, что происходит до вызова этой функции. Мы можем посмотреть на реализацию одной из вышеуказанных функций:

void WebGLMultiDraw::multiDrawArraysWEBGL(GCGLenum mode, Int32List firstsList, GCGLuint firstsOffset, Int32List countsList, GCGLuint countsOffset, GCGLsizei drawcount)
{
    if (!m_context || m_context->isContextLost())
        return;

    if (!validateDrawcount("multiDrawArraysWEBGL", drawcount)
        || !validateOffset("multiDrawArraysWEBGL", "firstsOffset out of bounds", firstsList.length(), firstsOffset, drawcount)
        || !validateOffset("multiDrawArraysWEBGL", "countsOffset out of bounds", countsList.length(), countsOffset, drawcount)) {
        return;
    }

    m_context->graphicsContextGL()->multiDrawArraysANGLE(mode, makeSpanWithOffset(firstsList, firstsOffset), makeSpanWithOffset(countsList, countsOffset), drawcount);
}

В JS спецификации функций определены так:

void ext.multiDrawArraysWEBGL(mode,
    firstsList, firstsOffset,
    countsList, countsOffset,
    drawCount);
  • mode:

    • gl.POINTS: Отрисовывает одну точку.
    • gl.TRIANGLES: Отрисовывает треугольник для группы из трех вершин.
  • firstsList:

    • Int32Array или массив (из GLint), задающий список начальных индексов для массивов векторных точек.
  • firstsOffset:

    • GLuint, определяющий начальную точку в массиве firstsLists.
  • countsList:

    • Int32Array или массив (из GLsizei), задающий список количеств индексов для рендеринга.
  • countsOffset:

    • GLuint, определяющий начальную точку в массиве countsList.
  • drawCount:

    • GLsizei, задающий количество экземпляров диапазона элементов для выполнения.

Взглянув на реализацию, мы видим, что можем управлять смещением и drawcount, чтобы отрисовывать за пределами размера буфера : )

Итак, наш PoC находится здесь ...

Тест

11pro

Как видите, наша веб-страница просто вылетела, потому что validateOffset(), вызываемый в multiDrawArraysWEBGL(), не проверяет, находится ли наш firstsOffset в диапазоне [0, size-drawcount], и мы рисуем за пределами фактического буфера. Вызов функции m_context->graphicsContextGL()->multiDrawArraysANGLE() реализован в сторонних компонентах WebKit, известных как ANGLE, и в нем нет никаких проверок перед рендерингом, поэтому мы вызываем сбой, записывая некорректное значение в область памяти.

К сведению, псевдокод multiDrawArraysANGLE() работает так:

      for(i=0; i<drawcount; i++) {
        if (*(counts+i)>0) DrawArrays(mode, *(firsts+i), *(counts+i));
      }

А с примененным патчем он ничего не отрисует и вернет false через вызов функции validateOffset():

12pro

js) ...

Благодарности

PARS Defense Team

Мы нанимаем новых членов команды, свяжитесь с нами: info[at]parsdefense.com

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