Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2022-22629 — CVE-2022-22629 Proof of Concept | Kitploit
工具/GitHubGitHub/lck0/cve-2022-22629
Vulnerability AnalysisExploitationWeb Security
GitHublck0/cve-2022-22629

CVE-2022-22629

CVE-2022-22629 Proof of Concept

查看仓库
53年前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2022-22629 概念验证

本文是关于在 Safari 15.4 安全更新中修复的 WebGL 漏洞的概念验证。

bug

如果你想详细了解 WebGL 的工作原理,可以使用以下官方资源,因为我们将在这里讨论漏洞的具体细节:

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

此概念验证并非关于如何利用原始体来利用此漏洞,我们只讨论漏洞分析和如何使 Web 内容崩溃 : )

介绍

WebGL 是一种 JavaScript API,用于在浏览器中渲染 2D 和 3D 图形。它使用 ANGLE 组件作为其主要 WebGL 后端,显著提高了与其他浏览器的兼容性,并在 WebKit 中实现了符合标准的 WebGL 2.0。WebGL 为开发者提供了许多扩展,以便进行优化渲染。因此,我们将研究我们所关注的扩展。

WebGL 中的扩展

extension

因此,该 API 提供了几种用于不同目的的扩展。我们将要讨论的漏洞存在于 EXT_ 中。

您可以从这里了解有关扩展的更多详细信息:

https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API/Using_Extensions

总之,让我们转向这个漏洞吧 :)

漏洞分析

WEBGL_multi_draw 扩展

WEBGL_multi_draw 扩展是 WebGL API 的一部分,允许通过单个函数调用渲染多个图元。这可以提高 WebGL 应用程序的性能,因为它减少了渲染器中的绑定开销,并通过统一数据加速 GPU 线程时间。

该扩展公开了 EXT_multi_draw_arrays 功能中的 Multi* 绘制调用变体,以及 ARB_shader_draw_parameters 为 OpenGL 公开的顶点着色器内置变量 gl_DrawID。

这些函数的行为与标准函数 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/

此扩展类似于 WebGL API 的 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 版本中,因为 Apple 的 iOS 中仅 Safari 15 支持此扩展。

补丁非常容易理解,它明确指出这是在渲染过程中发生的堆缓冲区溢出。此函数在 WebGLMultiDraw.cpp 中我们上面提到的所有操作 [1] 中被调用。让我们了解在调用此函数之前发生了什么。我们可以看看上面某个函数的实现:

root@kitploit:~
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 中,函数规范定义如下:

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

    • gl.POINTS:绘制单个点。
    • gl.TRIANGLES:为每组三个顶点绘制一个三角形。
  • firstsList:

    • 一个 Int32Array 或 Array(GLint 类型),指定向量点数组的起始索引列表。
  • firstsOffset:

    • 一个 GLuint,定义进入 firstsLists 数组的起始点。
  • countsList:

    • 一个 Int32Array 或 Array(GLsizei 类型),指定要渲染的索引数量列表。
  • countsOffset:

    • 一个 GLuint,定义进入 countsList 数组的起始点。
  • drawCount:

    • 一个 GLsizei,指定要执行的元素范围实例数。

查看实现,我们可以看到,我们可以控制 offset 和 drawcount,以在缓冲区大小之外进行绘制操作 : )

因此,我们的 POC 在这里……

测试

11pro

如您所见,我们的网页崩溃了,因为 multiDrawArraysWEBGL() 中调用的 validateOffset() 没有检查我们的 firstsOffset 是否在范围 [0, size-drawcount] 内,并且我们在实际缓冲区大小之外进行绘制。函数调用 m_context->graphicsContextGL()->multiDrawArraysANGLE() 是由 WebKit 的第三方组件 ANGLE 实现的,它在渲染之前没有任何检查,因此我们通过向内存区域写入一些错误值导致崩溃。

顺便一提,multiDrawArraysANGLE() 的伪代码工作方式如下:

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

而应用补丁后,它将不会渲染任何内容,并通过 validateOffset() 函数调用返回 false:

12pro

致谢

PARS 防御团队

我们正在招聘新团队成员,请联系我们:info[at]parsdefense.com

下载工具