当前位置: 首页 > 科技观察

通过逆向工程发现FacebookGameroom中的安全漏洞

时间:2023-03-21 23:22:09 科技观察

去年年底,我受邀参加了Facebook的Bountycon活动,这是一个仅限邀请的应用程序安全会议,其中包括现场黑客会议。虽然参与者可以在任何Facebook产品中提交错误,但Facebook邀请我们关注Facebook游戏。之前测试过Facebook的产品,我知道这将是一个艰巨的挑战。这些年来,他们的安全控制变得更加严格——即使是像跨站点脚本攻击这样的简单错误也很难发现,这就是为什么他们为他们支付非常高的赏金。因此,顶级白帽黑客往往会从第三方软件的角度来利用Facebook的安全漏洞,例如OrangeTsai著名的MobileIronMDM漏洞。鉴于我的时间有限(出于某种原因,我迟到了),我决定不进行全面的漏洞研究,而是专注于对FacebookGaming的访问控制进行简单的安全审计。然而,正如人们所预料的那样,安全性对移动和Web应用程序都有好处。经过一番挖掘,我发现了FacebookGameroom程序,这是一个用于玩Facebook游戏的本地Windows客户端。因此,我开始了将攻击性逆向工程应用于本机桌面应用程序的启蒙之旅。关于FacebookGameroom如果您没有听说过FacebookGameroom-这很正常,我以前从未听说过。事实上,Gameroom于2016年11月发布,一直被誉为Steam的有力竞争对手,支持Unity、Flash和最近的HTML5游戏。然而,近年来,随着流媒体的兴起,Facebook将注意力转向了其移动和网络平台。事实上,Gameroom计划于今年6月退休。幸运的是,当我挖出其中的安全漏洞时,它还没有退出市场。我注意到的第一件事是安装Gameroom时无需提升任何权限。它似乎是一个循序渐进的安装:首先,额外的文件是通过一个小的安装程序从网上下载的,也就是说,它的安装程序不是一体的。其实我很快就找到了安装目录,就是C:\Users\\AppData\Local\Facebook\Games因为大部分用户级的应用都在这个C:\Users\\AppData文件夹,所以我很快找到了安装目录。此文件夹包含许多.dll文件以及几个可执行文件。有几件事对我很重要:1.Gameroom附带的7zip可执行文件(7z.exe和7z.dll)可能已过时且易受攻击。2.Gameroom将用户会话数据存储在CookiesSQLite数据库中,这对攻击者来说是一个非常有吸引力的目标。3.Gameroom包含CefSharp库(CefSharp.dll),这是经过进一步研究后的C#嵌入式Chromium浏览器。第三点说明Gameroom是用.NET框架写的。我们知道.NET框架可以将程序编译成通用中间语言(CIL)代码而不是机器代码,也就是这些代码可以运行在通用语言运行时应用程序虚拟机中。这样做有很多好处,例如提高.NET应用程序的互操作性和可移植性。但是,由于这些应用程序被编译为CIL而不是纯机器代码,因此将这些应用程序反编译回接近源代码的过程也容易得多。DNSpy是.NET程序集的事实标准。逆向工程师可以使用DNSpy轻松调试和分析.NET应用程序,包括对其进行实时修改。因此,我将FacebookGameroom.exe拖入DNSpy并开始分析。挖掘漏洞函数首先,我们开始寻找漏洞函数,比如不安全的反序列化函数等,限于篇幅,反序列化攻击这里不再详细介绍。简而言之,这涉及将数据类型转换为易于传输的格式,然后再将它们转换回来。如果处理不当,这可能会导致严重的漏洞。例如,Microsoft已警告不要使用BinaryFormatter,因为BinaryFormatter不安全且无法确保安全。不幸的是,当我搜索字符串“Deserialize”时,弹出了BinaryFormatter。但是,我还需要找到易受攻击的代码路径。为此,我右键单击搜索结果,选择“分析”,然后按照“使用者”链找到Gameroom使用BinaryFormatter.Deserialize的位置。最终,这使我找到了System.Configuration.ApplicationSettingsBase.GetPreviousVersion(string)和System.Configuration.ApplicationSettingsBase.GetPropertyValue(string)函数。Gameroom在启动时使用反序列化功能来检索其应用程序的相关设置——但这些设置从何而来?查看安装文件夹,我找到了fbgames.settings,它是一个序列化的blob。因此,如果我在此文件中注入恶意反序列化负载,我可以获得代码执行。不过在那之前,我需要找到一个反序列化工具。根据已知的反序列化工具列表,我进一步搜索发现Gameroom使用了WindowsIdentity类。在此基础上,我开发了一个代码执行漏洞的概念验证过程:1.使用ysoserial反序列化攻击工具,通过命令ysoserial.exe-fBinaryFormatter-gWindowsIdentity-oraw-c"calc"-t>fbgames.settings生成相应的代码执行负载。2.接下来,我将fbgames.settings复制到C:\Users\3。最后,我打开了FacebookGameroom,计算器弹出来了!虽然获得代码执行权限非常令人兴奋,但在与Facebook团队进一步讨论后,我们一致认为这不符合他们的威胁模型。因为Gameroom是作为用户级应用程序执行的,所以没有提升权限的机会。此外,由于覆盖文件需要某种级别的访问权限(例如,需要批准才能公开列出的恶意Facebook游戏),因此没有可行的远程攻击媒介。在本机应用程序造成的不同威胁环境中,我学到了一个重要的教训——最好在深入研究代码级漏洞之前寻找可行的远程攻击媒介。规划探索路径您是否曾经单击电子邮件中的链接并神奇地启动了Zoom?幕后发生了什么?这真的很简单,它只是使用自定义URI方案,让您可以像链接一样打开应用程序。例如,Zoom已经注册了zoommtg:URI方案来解析如下链接:zoommtg:zoom.us/join?confno=123456789&pwd=xxxx&zc=0&browser=chrome&uname=Betty。此外,我注意到Gameroom使用自定义URI方案,因此它可以在单击网络浏览器中的链接后自动打开Gameroom。搜索代码后,我发现Gameroom通过FacebookGames\Program.cs检查fbgames:URIscheme:privatestaticvoidOnInstanceAlreadyRunning(){Uriuri=ArgumentHelper.GetLaunchScheme()??newUri("fbgames://");if(SchemeHelper.GetSchemeType(uri)==SchemeHelper.SchemeType.WindowsStartup){return;}NativeHelpers.BroadcastArcadeScheme(uri);}即使已经用fbgames://URI打开了Gameroom,它也会通过SchemeHelper类:publicstaticSchemeHelper继续解析。SchemeTypeGetSchemeType(Uriuri){if(uri==(Uri)null)returnSchemeHelper.SchemeType.None;stringhost=uri.Host;if(host=="gameid")returnSchemeHelper.SchemeType.Game;if(host=="launch_local")returnSchemeHelper.SchemeType.LaunchLocal;returnhost=="windows_startup"?SchemeHelper.SchemeType.WindowsStartup:SchemeHelper.SchemeType.None;}publicstaticstringGetGameSchemeId(Uriuri){if(SchemeHelper.GetSchemeType(uri)!=SchemeHelper.SchemeType.Game)return(string)null;stringstr=uri.AbsolutePath.Substring(1);intnum=str.IndexOf('/');intlength=num==-1?str.Length:num;returnstr.Substring(0,length);}如果URI包含gameid主机,它将被解析为SchemeHelper.SchemeType.Game.Game如果它使用launch_local主机,它将被解析为SchemeHelper.SchemeType.LaunchLocal。因此,从最有希望的launch_local路径开始,我将其追溯到FacebookGames.SchemeHelper.GenLocalLaunchFile(Uri):=1){result=null;}elseif(!(awaitnewXGameroomCanUserUseLocalLaunchController().GenResponse()).CanUse){result=null;}else{stringtext=uri.LocalPath.Substring(1);result=((MessageBox.Show(string.Format("Areyousureyouwanttorunfile\n\"{0}\"?",text),"ConfirmFileLaunch",MessageBoxButtons.YesNo)==DialogResult.Yes)?text:null);}returnresult;}不幸的是,即使我可以通过fbgames://launch_local/C:/evilapp.exe之类的URI启动系统中的任意文件(如Facebook所述),我仍然被确认对话框阻止。我试图用格式字符串和非标准输入绕过这个对话框,但没有成功。所以,我转向了gameid路径,它根据URI中的游戏ID打开FacebookURL。例如,如果您想在Gameroom中启动WordsWithFriends,您可以在浏览器中访问fbgame://gameid/168378113211268,Gameroom将在本地应用程序窗口中打开https://apps.facebook.com/168378113211268。但是,我发现GetGameSchemeId将从URI中提取ID并将其添加到app.facebook.comURL,但是,它不会验证slug是否是有效ID。因此,攻击者可以将本地应用程序窗口重定向到Facebook上的任何其他页面。publicstaticstringGetGameSchemeId(Uriuri){if(SchemeHelper.GetSchemeType(uri)!=SchemeHelper.SchemeType.Game)return(string)null;stringstr=uri.AbsolutePath.Substring(1);intnum=str.IndexOf('/');intlength=num==-1?str.Length:num;returnstr.Substring(0,length);}例如,fbgame://gameid/evilPage会将Gameroom窗口重定向到https://apps.facebook.com/邪恶的页面。但是我如何才能重定向到Gameroom中攻击者控制的代码?有多种方法,包括滥用app.facebook.com上的开放重定向漏洞。不幸的是,当时我手头没有一个这样的漏洞。另一种方法是重定向到允许将自定义代码嵌入到iframe中的Facebook页面或广告。在这一点上,我遇到了障碍。我需要重新编写GetGameSchemeId的代码,因为它只需要URI路径中的第一个slug,所以fbgame://gameid/evilPage/app/123456会将本机应用程序窗口定向到https://apps.facebook.com/evilPage,并将删除/app/123456。幸运的是,我还可以使用其他代码小工具。另外,Gameroom中使用的Chrome版本确实有点过时:63.0.3239.132——而当时的版本是86.0.4240.75。因此,它不支持较新版本的Facebook页面。经典的Facebook页面版本接受一个sk参数,这样https://apps.facebook.com/evilPage?sk=app_123456在https://apps生成一个带有攻击者控制代码的自定义选项卡。facebook.com/evilPage/app/123456!但是我们如何才能将额外的查询参数注入到我们的自定义方案中呢?不要忘记Gameroom会丢弃第一个URL段之后的所有内容,包括查询参数。真的吗?回头看FacebookGames/SchemeHelper.cs,发现GetCanvasParamsFromQuery:publicstaticIDictionary{if(uri==(Uri)null)return(IDictionarystringstringToUnescape;if(!UriHelper.GetUrlParamsFromQuery(uri.ToString())).TryGetValue("canvas_params",outstringToUnescape))return(IDictionarystringstr=Uri.Uri.UnescapeDataString(stringToUnescape);try{returnJsonConvert.DeserializeObject