CS:GO中的四个逻辑漏洞其中通过客户端远程代码执行(RCE)
2023-5-14 22:13:45 Author: Ots安全(查看原文) 阅读量:52 收藏

长话短说¶

我们在流行的反恐精英:全球攻势游戏中发现了三个独立的远程代码执行 (RCE) 漏洞。当游戏客户端连接到我们的恶意 python CS:GO 服务器时,每个漏洞都会被触发。这篇文章详细介绍了我们通过 CS:GO 二进制文件的旅程,并对各种已识别的错误进行了技术深入研究。最后,我们展示了一个概念验证 (POC) 漏洞,该漏洞利用四种不同的逻辑错误在游戏客户端中远程执行代码,当客户端连接到服务器时触发。

介绍¶

日期为 04/28/2021 的CS :GO 补丁修复了几个关键漏洞,包括我们的三个关键错误。这篇文章描述了我们的方法以及我们如何发现三个关键漏洞。我们展示了一个由四个逻辑错误组成的错误链,并通过巧妙地组合它们来解释这些错误如何导致客户端上的远程代码执行 (RCE)。

虽然这篇文章确实解释了四个逻辑漏洞,但它的重点是我们研究的方法。首先,我们查看 CS:GO 游戏的现有研究,并进行一般性介绍,以减轻复杂客户端逆向工程的痛苦。该帖子随后介绍了 CS:GO 网络协议的基本概念fast_dl,并Cvars详细介绍了四个不同的逻辑错误。将这些错误结合起来就可以通过仅连接到恶意的、攻击者控制的服务器来利用 CS:GO 客户端的概念证明。

反恐精英:GO ¶

免费游戏《反恐精英:全球攻势》(CS:GO)继续大受欢迎,每月有 2100 万玩家,这主要是因为许多社区托管服务器提供的游戏模式种类繁多。2012 年的游戏基于更早的源引擎 (2004),以PortalHalf-Life 2Left 4 Dead等游戏而闻名。源引擎反过来使用其前身GoldSrc (1998)Quake 引擎 (1996)的组件. 这段历史已经表明,强大而复杂的源代码引擎拥有一些组件,在编程时安全性尚未处于前台。

许多游戏模式、社区服务器和模组支持都会造成损失:一个很大的攻击面。纹理、3D 模型和 AI 导航点等许多文件格式通过各种解析器处理,数据完全由攻击者控制,因为数据直接从 CS:GO 服务器发送。此外,源引擎在 UDP 的基础上实现了自己的类似 TCP 的网络堆栈,在如此复杂的实现中存在所有相关问题。网络实施已经在其他攻击中被利用。

BUG 1:从服务器执行特权命令

这个错误允许攻击者在客户端上执行通常只在单人游戏模式下工作的“特权”命令

为了验证我们的自定义 python CS:GO 服务器是否确实在工作,我们将命令发送echo Hello World!到客户端,并且正如预期的那样,在游戏控制台上CNETMsg_StringCmd收到了输出。Hello World!随机地,我们也尝试发送quit命令。游戏结束了!我们无法相信允许服务器这样做。事实证明,这样做通常是不允许的:在SourceMod的帮助下,一个源引擎修改框架也可以向客户端发送消息,我们使用官方和修改后的服务器重新创建了相同的设置。结果FCVAR_SERVER_CAN_EXECUTE prevented server running command: quit:我们找到入口错误了吗?错误究竟是如何发生的?

源引擎单人游戏在内部使用本地托管的源引擎服务器。然后单人客户端连接到自己的服务器加入游戏。这个单人服务器当然应该有更深远的权利,比如改变客户端的键盘布局或者截屏。

如果最多只有一个客户端可以连接到服务器,则多人服务器被认为是本地的,因此具有特权的单人服务器。漏洞在于确定服务器类型:可以连接到服务器的最大客户端数由变量控制,m_nMaxClients并在连接到服务器时由客户端接收。一个偶然的机会,我们的 Python 服务器将变量设置m_nMaxClients为 1。这样我们就可以在客户端执行特权命令了!


Host_IsSinglePlayerGame 检查

BUG 2:由于扩展名剥离导致的任意文件下载

此错误允许攻击者下载具有任意文件扩展名的文件,绕过扩展名过滤器

源引擎服务器可以向客户端发送额外的游戏文件,例如地图或玩家模型。数据传输可以通过源网络协议或 HTTP 完成fast_dl。为了防止恶意文件被发送到客户端,某些文件扩展名,如*.exe, *.dll,*.ini被阻止。

如果fast_dl设置了该选项,附加内容将从指定的 HTTP 服务器加载,而不是直接从 CS:GO 服务器加载。该 URL 由函数根据服务器名称和完整文件名动态生成snprintf(p_cResult, 256, "%s/%s", p_cServerName, p_cFileName)。该snprintf函数将结果字符串的长度限制为 256 个字符,从而从文件名中截断不必要的字符。

但是 和p_cServerName都p_cFileName可以有 256 个字符的长度!像这样的文件名././[..]/file.AAA.BBB可以在扩展名之后专门终止.AAA,因为该.BBB部分被snprintf函数截断了。因此可以完全绕过潜在危险文件的过滤器!

以下源代码片段说明扩展名已被删除:

2017-04-26T00:15:42+00:00 [M:8167272392035836136]csgo/bin/osx64/server.dylib (+9.30 MiB)bin/osx64/engine.dylib (+5.17 MiB)bin/osx64/scaleformui.dylib (+3.23 MiB)csgo/bin/osx64/client.dylib (+12.13 MiB)bin/osx64/materialsystem.dylib (+2.18 MiB)


易受攻击的 snprintf 函数从字符串中剪切剩余数据

该漏洞是通过协议的代码分析发现的,近年来没有太大变化。fast_dl

BUG 3:任意文本文件写入游戏目录¶

此错误允许攻击者在游戏文件夹中(覆盖)写入任意文件

在这一点上,我们不确定如何组合前两个错误。因此,我们在 CS:GO 二进制文件中搜索了有用的特权命令。使用该命令,我们惊讶地发现此命令可以将任意文件写入任意游戏文件夹。由于类似的扩展名剥离错误,也可以指定任意文件扩展名,从而写入具有任意内容和任意扩展名的文本文件。con_logfile*.logsnprintf

具体来说,这个错误可以用来创建一个包含任意 CS:GO 命令的新配置文件。然后,“config”文件可以通过命令加载,从文件夹中读取文件。cfg/leak.logleak.logexec leak.logcfg

BUG 4:回退到禁用的签名检查

该漏洞允许攻击者以“不安全”模式启动 CS:GO 客户端,从而允许加载未签名的游戏二进制文件

启动 CS:GO 客户端时,通过匹配的哈希值来验证游戏 DLL 的完整性。只有在此验证之后,才能在官方服务器上播放。如果 DLL 验证失败,则会回退到该模式。这也可以通过额外的命令行参数来实现。只有在此模式下,才能加载未位于游戏路径中的其他 DLL。如果攻击者成功使DLL验证失败,他们可以创建自己的DLL,在配置中引用这些DLL,实现命令执行。在 Windows 上,攻击者可以指定在将 DLL 加载到进程中时执行的代码。因此,攻击者可以在客户端系统上执行任意代码。insecure、-insecure、bin/

Windows 可防止覆盖在正在运行的进程中加载的 DLL。因此,我们必须找到一个在游戏开始时经过验证但未加载到进程中的 DLL。幸运的是,我们发现 已被替换为 因此不再加载,但仍经过验证!因此,使用任意文本覆盖(错误 3)会导致验证失败。client.dllclient_panorama.dllclient.dll

完整的逻辑错误链¶

完整的错误链使用所有四个错误来:

  1. 在客户端上执行特权命令

  2. 将恶意 DLL 下载到游戏目录

  3. 替换 ,以便在游戏启动时加载恶意 DLLgameinfo.txt

  4. 损坏 以实现回退到模式client.dllinsecure

要理解以下步骤,我们仍然需要引入源引擎的两个典型元素:和:gameinfo.txtCVars

游戏信息.txt¶

所有基于源引擎的游戏实际上是基本半条命游戏的“附加组件”。游戏的资产和 DLL 从文件中定义的特殊路径加载:gameinfo.txt

"GameInfo"{  game  "Counter-Strike: Global Offensive"  title  "COUNTER-STRIKE'"  title2  "GO"  type multiplayer_only
[ ...]
FileSystem { SteamAppId 730 // This will mount all the GCFs we need (240=CS:S, 220=HL2). ToolsAppId 211 SearchPaths { Game |gameinfo_path|/exploit // NOTE: Added by our exploit Game |gameinfo_path|. } }}

通过设置为数组中的第一个,引擎会尝试从此路径加载缺少的 DLL。仅当在那里找不到要加载的元素时,才使用原始游戏路径。在游戏开始时加载的一个 DLL 是 。这意味着我们可以在 CS:GO 客户端加载 DLL 时放置一个新的并调用任意代码。|gameinfo_path|/exploit、FileSystemmatch、making.dllmatch、making.dll

CVars

CVars是SourceEngine游戏中的基本概念,随处可见。这些变量几乎控制了游戏中要设置的所有内容:路径、键绑定、十字准线的外观、游戏模式等。此外,许多反恐精英玩家可能已经听说过的传奇变量是.根据 ,这些设置也可以由服务器设置,从而覆盖本地选项。sv_cheats、CVar、CVar

连接后,客户端会告诉服务器在客户端设置了哪些本地,以便服务器可以做出相应的反应。例如,如果设置为在客户端,则服务器可以踢客户端。作为攻击者,我们需要从 CS:GO 客户端知道安装目录,以便我们可以利用并采用恰到好处的路径长度。遗憾的是,默认情况下,客户端不会发送包含当前游戏目录的 。因此,我们使用一个技巧来设置新的并将其发送回攻击者控制的服务器。基本思想:CVarssv_cheats1bug 2bug 4CVarCVAR GAMEBIN

  1. 执行“脚本”以设置leak.logCVar GAMEBIN

  2. 指示客户端重新连接到恶意服务器

  3. 重新连接后,全部并设置回恶意服务器CVars

详细信息涉及从配置文件调用命令以设置游戏的安装路径。我们利用攻击者编写的配置文件,其中包含命令。客户端必须执行配置文件,否则在下次服务器连接期间不会永久存储。该文件使用命令执行。之后,恶意服务器指示客户端重新连接。重新连接后,将泄漏回服务器。path、CVAR GAMEBIN、leak.log、path、CVar、leak.log、exec、CVar

漏洞链

视频¶

我们提供了上面概述的四个逻辑错误链的视频(见下文)。如果您在 00:29 秒停止视频,您会注意到 CS:GO 控制台和漏洞利用服务器中有趣的输出:

  • 泄漏是从漏洞利用服务器检索的GAMEBIN: f:\spiele\steam\steamapps\common\couter-strike global offensive\csgo\bin

  • CS:GO 控制台显示下载时间很长的文件,这些文件成功下载。如上所述,扩展名在下载过程中被剥离,从而导致下载 和 。././[..]/bin/matchmaking.dll.stf、././[..]/gameinfo.txt.stf、.stf、matchmaking.dll、gameinfo.txt

结语¶

人们经常问我们花了多少时间来构建这个漏洞利用链。不幸的是,我们无法确定花费的总时间。几个星期以来,我们在晚上在 Discord 上见面,交流想法、一起编程并分析我们的发现,直到凌晨。当时的阿兰在 CS:GO 中玩了大约 250 个小时的游戏时间,并且没有玩过一场在线比赛。我们“相对”很快就发现了这些漏洞,但对于他们的漏洞赏金计划,Valve 需要一个全链漏洞来证明 RCE 的影响。如果没有精心的演示,研究将在30%的时间后完成。因此,我们在RCE演示中投入了相当多的时间。

说到Valve:我们通过各种看起来很简单的HackerOne报告了解到Valve对CS:GO的高支出。当时的报告只需要证明内存损坏即可获得全额支出。在我们的三份不同的报告被迅速宣布有效后,我们最初的兴奋迅速消退,但即使在 13 个月和多次请求之后仍未修复。经过很大的压力和完全披露的威胁,这些错误终于得到了修复。每个错误的支出为7.5k,低于我们的预期。总而言之,这是一次发人深省的体验。

对我们来说,CS:GO 漏洞赏金之旅是我们第一次在一个项目中投入数周的时间。我们个人的收获主要是:

  • 不要只寻找批评性错误和速赢。

  • 链接您的错误以释放其全部潜力。

  • 睁大眼睛注意边缘情况和开发人员没有想到的事情。

  • 努力!如果撞墙寻找洞,不要过早放弃。

时间线:日期 行动

01.03.2020 我们发送带有PoC视频和漏洞利用设置的初始报告

01.03.2020 H1 在重现问题时遇到麻烦

03.03.2020 我们提供了一个漏洞利用 Docker 设置,以便更轻松地重现

06.03.2020 H1仍然无法重现该问题

21.03.2020 我们使用OpenVPN提供完整的服务器设置,以实现更轻松的可复制性

21.03.2020 H1 成功重现问题并将报告标记为已分类

01.06.2020 我们要求更新

03.06.2020 H1表示他们仍在研究该报告

18.09.2020 我们要求更新,因为总共已经过去了半年

22.10.2020 我们再次要求更新

27.10.2020 H1表示Valve仍在调查报告

01.03.2021 我们说“周年快乐”并要求更新

2021年<>月 我们联系其他向 Valve 提交错误的研究人员,并考虑在我们的报告中集体投诉

22.04.2021 我们写了一份声明,表达我们对这一过程的不满,并“保留在未来几周内披露调查结果的权利”

26.04.2021 H1表示,他们将报告标记为“内部经理”,并试图加快流程

30.04.2021 我们注意到问题已得到解决,并要求与 Valve 协调披露

01.05.2021 H1说“感谢您的报告”,我们收到了赏金

29.03.2022 我们要求披露报告,但到目前为止没有回应


点它,分享点赞在看都在这里


文章来源: http://mp.weixin.qq.com/s?__biz=MzAxMjYyMzkwOA==&mid=2247497712&idx=1&sn=b2d7a344e78ada425d601472ed705419&chksm=9badbebbacda37adb6d5d06223d21567d1a8b572e6d4bf6c9859bd75ae74839a4bacdaf731b8#rd
如有侵权请联系:admin#unsafe.sh