Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

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

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

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
POC-for-CVE-2023-41993 — CVE-2023-41993 的概念验证漏洞利用程序,针对 Safari 中 WebKit JIT 的类型混淆漏洞。通过堆操作和 GetterSetter 混淆提供 addrof/fakeobj 原语,从而在 WebContent 进程中实现任意读写。 | Kitploit
工具/GitHubGitHub/po6ix/poc-for-cve-2023-41993
漏洞分析漏洞利用Web应用程序漏洞利用Payload 开发二进制利用
GitHubpo6ix/poc-for-cve-2023-41993

POC-for-CVE-2023-41993

CVE-2023-41993 的概念验证漏洞利用程序,针对 Safari 中 WebKit JIT 的类型混淆漏洞。通过堆操作和 GetterSetter 混淆提供 addrof/fakeobj 原语,从而在 WebContent 进程中实现任意读写。

查看仓库
20237162年前Kitploit 审核通过

最受欢迎

查看全部 →

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

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2023-41993

针对 CVE-2023-41993 的 PoC 漏洞利用代码。 它只实现了到 addrof/fakeobj 的部分。 可靠性不太好。 如果你想改进它,可以尝试喷射 structure ID。

POC 链接

https://po6ix.github.io/POC-for-CVE-2023-41993/pwn.html

由于多次请求,我决定用 GitHub Pages 来托管。
祝我好运,希望 GitHub 不会封我……

已知受影响版本

  • MacOS 14.0
  • iOS 17.0, 17.1 beta 1
  • iPadOS 17.0

已知不受影响版本

  • iOS 16.1.1, 16.2, 16.5, 16.5.1, 16.6 beta 1, 16.6.1, 16.7.1, 17.1 RC
  • iPadOS 17 beta 1

问答

它只会崩溃

这是因为 pwn 函数中定义的 factor 值不适合你的设备。
针对这种情况,我让它使用 87 到 1088 之间的随机值。
所以你只需刷新几次就能找到正确的 factor 值。
从概率上讲,通常会在 100 次尝试内成功。
如果你能把成功案例中显示的信息发给我,那就更好了。

那么我能用它做什么?

这能为你提供针对 Safari webcontent 进程的读/写原语。
但要真正利用它,你还需要与其他组件进行串联。

简要说明

你可能想要一份详细的 writeup。 但遗憾的是,我抽不出时间写那东西。 所以我在这里记一些笔记,让你能理解它的工作原理。

如果你看过那个 commit,它涉及的是对 HeapLocation 的更改。 新增了一个 factor,用来判断节点是否相同。 它告诉我们,像 GetByOffset、MultiGetByOffset 这样的节点可能会被混淆。 但实际上这只是关于偏移(offset)的问题。 假设有两个偏移不同的 GetByOffset 节点。 其中一个会被 CSE 消除,剩下的那个会被使用。 所以这基本上是一种偏移混淆,但它并不能让你访问任意偏移。 因为要对此类节点进行 CSE,它们需要被 LICMPhase 提升(hoist)。 此阶段不允许提升执行写操作的节点。 因此 PutByOffset、MultiPutByOffset 节点不会发生同样的混淆。 另外,当 GetByOffset 被提升时,会调用 safeToExecute 函数来检查该节点是否合法可执行,并且只允许访问小于存储容量(inline/ool)的偏移。 因此,利用这个漏洞的思路是 GetterSetter。 如果你调用 Object.__defineGetter__ 定义一个属性,会创建 GetterSetter 对象,但它存储在属性存储中,通常无法访问。 但你可以利用这个偏移操作来访问它。 然后调用 Object 函数来触发类型混淆。

JSObject* JSCell::toObjectSlow(JSGlobalObject* globalObject) const
{
    Integrity::auditStructureID(structureID());
    ASSERT(!isObject());
    if (isString())
        return static_cast<const JSString*>(this)->toObject(globalObject);
    if (isHeapBigInt())
        return static_cast<const JSBigInt*>(this)->toObject(globalObject);
    ASSERT(isSymbol());
    return static_cast<const Symbol*>(this)->toObject(globalObject);
}

它会创建一个 SymbolObject,其内部值为 GetterSetter。 这是不正确的,因为 SymbolObject 的内部值本应是 Symbol 实例,而不是 GetterSetter。

let getterSetter = jitme(1);
let symbolObject = Object(getterSetter);

symbolObject.description; // call the getter
String Symbol::description() const
{
    auto& uid = m_privateName.uid();
    return uid.isNullSymbol() ? String() : uid;
}

然后当你调用 description getter 时,它会返回一个 String 实例。 这是 Symbol.m_privateName 与 GetterSetter.m_getter 之间的类型混淆。 每次调用这个 getter,它都会增加 m_privateName.m_uid 的引用计数字段,该字段位于偏移量 0x0 处。 这非常有用,因为这个偏移量正是 getter 函数 structure ID 所在的位置。 多次调用这个函数,你就可以改变 JSFunction 实例的 structure ID。 我准备了另一个具有很多属性的类型。 然后如果你把 structure ID 同步为与它相同,就可以对属性存储进行越界写入。 这直接提供了 addrof/fakeobj 原语。

参考

  • Int64 模块:https://github.com/saelo/jscpwn
下载工具