百度爱采购网站官网,custed谁做的网站,仿别人的网站,asp企业网站自助建站系统免费版超漂亮版引言
MS-RPC 是 Windows 网络中广泛使用的协议#xff0c;许多服务和应用程序都依赖它。 因此#xff0c;MS-RPC 中的漏洞可能会导致严重后果。 Akamai 安全情报小组在过去一年中一直致力于 MS-RPC 研究。 我们发现并利用了漏洞#xff0c;构建了研究工具#xff0c;并编写…引言
MS-RPC 是 Windows 网络中广泛使用的协议许多服务和应用程序都依赖它。 因此MS-RPC 中的漏洞可能会导致严重后果。 Akamai 安全情报小组在过去一年中一直致力于 MS-RPC 研究。 我们发现并利用了漏洞构建了研究工具并编写了协议的一些未记录的内部结构。
Akamai 研究员 Ben Barnea 在 Microsoft Windows RPC 运行时中发现了三个重要漏洞这些漏洞的基本评分均为 8.1CVE-2023-24869、CVE-2023-24908 和 CVE-2023-23405。这些漏洞可能导致远程代码执行。由于 RPC 运行时库已加载到所有 RPC 服务器中并且这些服务器通常由 Windows 服务使用因此所有 Windows 版本桌面版和服务器版都会受到影响。产生这些漏洞的原因是 RPC 运行时使用的三种数据结构中的整数溢出。目前 Akamai 已负责任地向 Microsoft 披露这些漏洞并且这些漏洞于 2023 年 3 月的补丁星期二得到解决。
虽然之前的一些文章主要关注服务中的漏洞但我们将在本篇文章中探讨 RPC 运行时MS-RPC 的 “引擎”中的漏洞。这些漏洞与我们在 2022 年 5 月发现的漏洞类似。 整数溢出模式
这三个新漏洞有一个共同的主题 —— 它们都是由于插入三个数据结构时出现整数溢出而存在的
SIMPLE_DICT只保存值的字典SIMPLE_DICT2同时保存键和值的字典队列
所有这些数据结构都是使用动态数组实现的每次数组变满时该数组都会增长。 这是通过分配为当前数组分配的内存的两倍来实现的。 此分配容易受到整数溢出的影响。
图 1 显示了 RPC 运行时的反编译代码。它显示了 SIMPLE_DICT 结构的插入过程以及可以触发整数溢出的易受攻击的代码行高亮显示。 图 1SIMPLE_DICT 结构扩展中的整数溢出 探索产生漏洞的原因
要触发漏洞我们需要了解其根本原因弄清楚是否存在指向漏洞函数的流程以及触发需要多长时间。
为了简洁起见我们将描述这三个漏洞之一队列数据结构中的漏洞。由于其他整数溢出本质上是相似的因此以下各节中进行的分析可以互换进行。 了解整数溢出
队列是一种简单的 FIFO先进先出数据结构。 RPC 运行时中的队列是使用一个结构体实现的该结构体包含队列条目数组、当前容量以及队列中最后一项的位置。
当一个新条目添加到队列中时假设有一个可用槽所有项目都会在数组中向前移动并且新项目将添加到数组的开头。 然后队列中最后一项的位置递增。
当发生出列时最后一个项目将被拉出并且最后一个项目的位置会递减如图 2 所示 图 2排队和出队操作期间的队列结构
如前所述该漏洞发生在插入新条目时。 如果动态数组已满代码将执行以下操作
分配具有以下大小的新数组 当前容量 * 2 * sizeof (QueueEntry)将旧项目复制到新数组释放旧项目数组容量加倍
对于 32 位系统在计算新数组大小时会发生溢出
我们用 0x10000000 (!) 个项目填充队列。发生扩展。新分配的大小计算为0x10000000 * 16。由于溢出新分配大小为 0。分配了一个零长度数组。代码将旧的 items 数组复制到新的小数组中。这将导致野生副本线性大副本。
在 64 位系统上该漏洞无法被利用因为会有大量的分配失败。这会导致代码正常退出因而不会触发任何越界写入。尽管 64 位系统不会受到此问题的影响但它们仍然很容易受到其他整数溢出的影响在 SIMPLE_DICT 和 SIMPLE_DICT2 中。 代码流
RPC 连接使用 OSF_CONNECTION 类表示。每个连接可以处理多个客户端调用 (OSF_SCALL)但在每个给定时间仅允许在连接上运行一个调用而其他调用则排队。
因此一个使用队列的有趣函数是 OSF_SCONNECTIONMaybeQueueThisCall。 它作为调度已到达连接的新调用的一部分进行调用。在这种情况下队列用于在处理另一个调用时 “保持” 传入调用。
因此我们有一种用户控制的方式来填充队列通过一个接一个地发送客户端调用但此函数提出了一个要求连接当前正在处理一个调用。这意味着如果我们想要填充队列我们需要有一个需要时间才能完成的调用。在处理调用时我们将发送多个新调用这些调用将填满调度队列。
什么样的函数调用需要最长的时间才能完成
最佳候选者是可以在其中引起无限循环的函数。第二个最佳选择是身份验证强制漏洞因为服务器会连接到我们 - 因此我们可以控制响应时间。最后的手段是具有复杂逻辑的复杂函数或处理大量数据并因此需要大量时间才能完成的函数。
我们决定使用我们自己的身份验证强制漏洞。 触发所需的时间
到目前为止我们了解了填充队列需要什么以及如何完成。 但一个重要的问题出现了 —— 它是否是实用的
我们对发生整数溢出的变量的控制程度最低。一次只能递增一个类似于 refcount引用计数溢出。这种整数溢出比整数溢出略差整数溢出是我们完全控制的两个变量相加或相乘或者当添加的大小可以在一定程度上控制时例如数据包大小。
正如前面所描述的我们必须分配 0x10000000 (~268M) 项。 这是非常庞大的数量。
尝试在我的计算机上触发漏洞的速度约为每秒 15 到 20 个排队调用。这意味着在普通机器上大约需要 155 天才能触发它我们预计每秒会产生更多的排队调用。RPC 运行时间这么慢是有什么原因吗它不是多线程的吗
我们的假设是多个线程同时处理同一连接的不同调用并将其排队。 经过一番逆向工作我们发现实际的流程有点不同。 MS-RPC 数据包处理
在调度调用之前代码会旋转到一个新的线程如果需要的话并调用 OSF_SCONNECTION::TransAsyncReceive。 TransAsyncReceive 尝试在同一连接上接收请求。 然后它将请求提交给新线程通过调用 CO_SubmitRead。
另一个线程从 TppWorkerThread 中选取请求最终导致 ProcessReceiveComplete后者调用 MaybeQueueThisCall 将 SCALL 排队到调度队列中。然后它向上传播并尝试接收对此连接的新请求。
因此虽然我们可能有多个线程在运行但实际上只有一个线程用于连接。 这意味着我们无法同时将多个线程的调用添加到队列中。 数据包 “剩余”
我们试图找到每秒进行更多调用的方法以最大限度地减少触发漏洞所需的时间。在逆向接收代码时我们注意到如果数据包的长度大于数据包中的实际 RPC 请求则 RPC 运行时会保存剩余部分。稍后当它检查新请求时它不会立即使用套接字。它会首先检查是否有数据包 “剩余”如果有它会根据剩余数据提供新的请求。
这让我们能够发送更少的数据包每个数据包都包含最大数量的请求。当我们尝试这样做时每秒排队的调用数量保持相对不变因此这似乎是没有任何帮助的。 总结
尽管预计利用这些漏洞的可能性很低但我们已将它们添加到我们去年对 MS-RPC 研究中发现的重要漏洞列表中。 重要的是要记住即使是难以利用的漏洞对于有能力且有耐心的攻击者来说也是一个机会。
虽然 MS-RPC 已经存在了几十年但它仍然存在有待发现的漏洞。我们希望这项研究能够鼓励其他研究人员研究 MS-RPC 及其所呈现的攻击面。 我们要感谢 Microsoft 的快速响应并解决问题。
欢迎关注 Akamai 第一时间了解高可用的 MySQL/MariaDB 参考架构以及丰富的应用程序示例。