Okta 验证 Windows 远程代码执行 - CVE-2024-0980

admin 2024年5月7日13:00:41评论9 views字数 4334阅读14分26秒阅读模式

Okta 验证 Windows 远程代码执行 - CVE-2024-0980

在 Windows 上使用 Okta 验证 Poppin shell

这些天我很少有机会去寻找 bug。幸运的是,在假期里,我找到了一些空闲时间。一开始就像我通常做的那样,查看我的计算机上正在运行什么软件。

Okta 验证 Windows 远程代码执行 - CVE-2024-0980

不久前,我在我的 Windows 机器上安装了 Okta verify,因为它是某些“增强型”2FA 所必需的,我需要访问某个东西。几个月后,它坐在那里做它该做的事。我在 google 上搜索 Okta 是否有 bug 赏金计划,因为即使我有一些时间,但如果我发现了东西,得到报酬就太好了。我很高兴地发现 Okta 与 Bugcrowd 有一个错误赏金,Okta verify 也在其中,而且奖金看起来不错,几乎太好 了。

Okta 验证 Windows 远程代码执行 - CVE-2024-0980

当接近随机 Windows 服务时,我从通常的错误搜寻流程开始。这通常包括寻找通常容易实现的目标。可以在这里找到一篇关于要查找的内容类型的好文章。

启动 Sysinternal 的 Procmon,我看到有一个名为 Okta.Coordinator.Service 的服务正在以 SYSTEM 身份运行。无需深入了解细节(即因为 Okta 尚未修复它或为其颁发 CVE), 我发现了一个东西。我提交了报告并立即得到了报酬。

Okta 验证 Windows 远程代码执行 - CVE-2024-0980

让我们开始吧

我还没有将 Okta.Coordinator.Service.exe 放入反汇编程序中,但我敢打赌它是一个 .NET 应用程序。我的猜测来自于它的名称以及它旁边有一个 Okta.Coordinator.Service.exe.config 文件的事实,您通常在 .NET 应用程序中看到该文件。

Okta 验证 Windows 远程代码执行 - CVE-2024-0980

当我在 JetBrains dotPeek 中打开可执行文件时,我可以确认它确实是一个 .NET 应用程序。该二进制文件似乎是一个服务包装器。它处理与服务相关的功能:安装、卸载、启动、停止等。它引用 Okta.AutoUpdate.Executor 类,该类恰好在同一目录中具有匹配的 DLL。

Okta 验证 Windows 远程代码执行 - CVE-2024-0980

继续查看 dotPeek 中的 DLL,我找到了该服务使用的代码。我注意到的第一件事是它设置了一个 NamedPipe 服务器,该服务器侦听更新 Okta 验证软件的命令。这是 Windows 中的常见设计范例,用于使低特权应用程序能够与高特权服务进行通信以执行更新,因为这些通常需要提升的特权。这是一个复杂的机制,很难正确执行,而且通常是查找错误的好地方。我能够使用一点 Powershell 来确认命名管道服务器的存在。

Okta 验证 Windows 远程代码执行 - CVE-2024-0980

接下来,我研究了如何启动更新以及攻击者可以操纵此过程的哪些方面。命名管道的处理程序处理一条简单的 JSON 消息,其中包含多个字段,其中一些字段根据预期值进行检查。主要感兴趣的字段是更新 URL。如果输入数据通过验证,软件将尝试从指定的 URL 获取有关最新可用更新包的详细信息。如下所示,在继续之前,将根据白名单验证 URL(子)域。目前,我将避免尝试满足/绕过此要求,而只需在测试计算机上的主机文件中添加一个条目。

Okta 验证 Windows 远程代码执行 - CVE-2024-0980

Okta 验证 Windows 远程代码执行 - CVE-2024-0980

通常在这个阶段,我会编写概念验证 (POC) 代码,以将 JSON 消息发送到命名管道,并检查软件是否连接到我控制的 Web 服务器。但由于我还没有发现任何潜在的漏洞,所以我跳过了这一步并继续前进。

从这里我查看了负责处理从攻击者控制的更新服务器检索到的 JSON 消息的代码。应用程序期望收到一条消息,其中包含有关更新包的元数据,包括版本控制和文件元数据对象数组。这些对象包含几个相关字段,例如下载 URL、大小、哈希、类型和命令行参数。提供的下载 URL 使用与之前相同的域检查算法进行验证。如果检查通过,软件将下载该文件并将其写入磁盘。这就是事情变得有趣的地方。该代码从接收到的元数据中解析下载 URL,并通过调用Path.Combine函数构建文件路径。

Okta 验证 Windows 远程代码执行 - CVE-2024-0980

多种因素综合在一起造成了严重的漏洞。最明显的是将Path.Combine函数与用户提供的数据一起使用。我在之前的一篇博客文章中深入讨论了这个问题。TLDR 是,如果提供完整路径作为该函数的第二个参数,则通常指定父文件夹的第一个参数将被忽略。下一个问题是如何解析文件名。该代码通过正斜杠分割文件位置 URL,并将最后一个元素作为文件名。问题(解决方案)是可以使用反斜杠在此处插入完整的 Windows 路径,并且它仍然是有效的 URL。由于该服务作为 SYSTEM 运行,因此我们有权访问任何地方。如果我们把所有这些放在一起,我们的有效负载看起来就像下面的脚本。

sha256_hash = hashlib.sha256()sha256_hash.update("AAAAA")lib_hash = sha256_hash.hexdigest()payload_name = "test.txt"class CustomRequestHandler(http.server.BaseHTTPRequestHandler): def do_GET(self): if self.path.startswith('/api'): # Handle GET requests here json_data = { "version": "5.0.0", "files": [ { "href": "https://test.okta.com/C:\%s" % payload_name, "size": len(payload), "hashValue": "abcd1234", "type": "Document", "fileHashes": { "SHA256": lib_hash }, "commandArgs": "", "requiresElevatedInstall": True },

现在我有一个潜在的错误需要测试,我为命名管道客户端制作 POC 以触发更新。幸运的是,该代码已存在于 .NET DLL 中,可供我重新利用。我的网络服务器代码也就位后,我发送请求来测试文件写入。正如我所希望的,文件写入成功了!

Okta 验证 Windows 远程代码执行 - CVE-2024-0980

很酷,但是影响怎么样!

我能够在 Windows 上以 SYSTEM 身份写入任意文件。如何利用它来实现按需远程代码执行?首先想到的是某种形式的DLL 劫持。我过去曾使用过幻影 DLL 劫持,但这更适合红队操作,因为时间限制并不是真正的问题。我真正需要的是在文件写入后立即强制执行的能力。

由于此服务背后的全部目的是安装更新,我可以用它来执行我的代码吗?我在文件写入后查看了代码,看看执行下载的更新包需要什么。看来文件对象元数据中的文件类型字段用于指示要执行哪个文件。如果设置了 EXE 或 MSI 文件类型,应用程序将在执行之前尝试验证文件签名以及任何提供的参数。进程启动器执行二进制文件,并将 UseShellExecute 设置为 false,因此不可能进行命令注入。

Okta 验证 Windows 远程代码执行 - CVE-2024-0980

我最初的想法是提供一个合法的 Okta 验证包,因为这会通过签名检查。然后我可以使用 ProcMon 来识别安装包中的 DLL 劫持。特权 DLL 劫持几乎发生在所有服务中,因为假设您已经需要写入特权位置的权限。但讽刺的是,我发现服务二进制文件实际上在签名验证之前包含了 DLL 劫持,以加载必要的加密库。如果我将 DLL 写入C:Program Files (x86)OktaUpdateServicewintrust.dll,它将在签名验证之前加载。

Okta 验证 Windows 远程代码执行 - CVE-2024-0980

太好了,现在我有办法从非特权用户到 SYSTEM 执行任意代码。“猜测” 这可能达不到 P1 或 P2 的标准,我开始考虑如何将其升级为远程代码执行。如果 RCE 没有获得 P1 那么什么可以呢?命名管道的有趣之处在于它们通常可以远程访问。这完全取决于设置的权限。查看下面的代码,它将完全控制设置为“BUILTINUsers”组。

Okta 验证 Windows 远程代码执行 - CVE-2024-0980

从网络中的远程系统进行的测试证实,当我尝试连接到命名管道时,权限被拒绝。几天后我有了一个想法。如果 Windows 系统是 Active Directory 域的一部分,则 BUILTIN/Users 组权限是否会自动转换为域中的“Domain Users”组?这意味着 AD 域中的任何用户都可以在安装了 Okta verify 的任何系统上远程执行代码。此外,考虑到该软件针对的是大型企业,它很可能会被纳入标准构建并广泛部署。因此,虽然不是明确的“域管理员”,但很有可能是这样。我必须找出答案,所以我在 AWS 中建立了一个测试 AD 网络,下面的视频展示了发生的情况。

快完成了

嗯,这似乎是一件大事,对吧?也许获得 P1(和 70k...)?我猜测没有 Okta 子域可供下载的小细节可能会阻止它登陆 P1。我曾在大型科技公司工作过,知道子域名被接管的报告很常见。然而,如果没有子域接管,该错误的重要性可能会被最小化。我决定花一些时间来寻找一个来完成漏洞利用链。在检查了标准错误赏金子域接管工具后,我只想到了一个可行的候选工具:oktahelpspot.okta.com。它指向一个没有开放端口的 IP,由一家名为 Arcustech 的小型 VPS 提供商管理。

在注册了一个帐户并进行了一些非常无辜的社会工程之后,我得到了以下回复。然后是第一个人的经理发来的第二封电子邮件。哦,好了,就这么多了。

Okta 验证 Windows 远程代码执行 - CVE-2024-0980

Okta 验证 Windows 远程代码执行 - CVE-2024-0980

下来想到的是利用自定义 Okta 客户端子域。每当新客户在 Okta 注册时,他们都会收到个性化的 Okta 子域来管理其身份提供商,例如 Trial-XXXXXXX.customdomains.okta.com。我找到了一种在 Web 管理应用程序中设置自定义路由的方法,该方法会将流量从自定义域重定向到用户定义的 URL。不幸的是,这个重定向是用 Javascript 实现的,而不是通过传统的 302 或 301 HTTP 重定向。因此,Okta 验证更新服务使用的 .NET HTTP 客户端不会执行 Javascript,因此不会像浏览器那样遵循重定向。

报告

此时,我决定是时候向 Okta 报告我的发现了。也就是说,因为他们当时为似乎是 Okta verify 的东西提供了奖金,我认为他们可能已经忘记了或者没有提及就包括了。其次,我不想冒被别人抢先的风险。我很高兴地向大家报告,他们接受了该报告,并作为 P2 给予我 13,337 美元的慷慨赏金。它的售价虽不及 7 万美元,也不是 P1,但也不容小觑。我要感谢 Okta 的赏金和快速解决。他们还善意地允许我撰写这篇博文,并随后发布了 CVE-2024-0980 以及建议。

最后一点,如果有人阅读本文找到了绕过子域验证检查的方法,我会非常感兴趣。我尝试了大多数常见的 URL 解析混淆技术以及各种编码技巧,但都没有成功。请在 X 上给我留言@rwincey

原文地址:https://www.securifera.com/blog/2024/05/02/okta-verify-for-windows-remote-code-execution-cve-2024-0980/

原文始发于微信公众号(Ots安全):Okta 验证 Windows 远程代码执行 – CVE-2024-0980

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年5月7日13:00:41
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Okta 验证 Windows 远程代码执行 - CVE-2024-0980https://cn-sec.com/archives/2707274.html

发表评论

匿名网友 填写信息