导语:Dell的Digital Delivery是一个购买和安装软件系统的平台,它允许用户购买或管理软件包,并在需要时重新安装某个软件。该平台默认在绝大多数Dell产品的系统上安装。
概述
在今年3月到4月期间,我开始对安装在笔记本电脑上的一系列Dell应用程序进行逆向。其中有很多程序都具有特权服务或者特权进程在运行,而这些服务或进程执行了不同的复杂操作。之前,我曾经披露过一个SupportAssist的本地权限升级(Local Privilege Escalation)漏洞(http://hatriot.github.io/blog/2018/05/17/dell-supportassist-local-privilege-escalation/),这次又在Digital Delivery platform中发现了另外一个。本文将对新发现的漏洞进行详细介绍,并分析该漏洞的利用方式。由于这一漏洞发现后未经披露就提交给了厂商,因此目前没有已知的EXP被公开。Dell已经针对此问题发布了安全公告,详细内容请参考:https://www.dell.com/support/article/us/en/04/SLN313559 。
此后,我计划再写一篇文章,详细介绍这个应用程序的内部结构和其他一些内容,以便为其他研究人员提供一些理论支撑。这两个应用程序都非常复杂,并且暴露出较大的攻击面。如果读者对大型C#/C++应用程序中的本地权限升级漏洞利用感兴趣,那么阅读此篇文章是一个很好的开始。
Dell的Digital Delivery是一个购买和安装软件系统的平台,它允许用户购买或管理软件包,并在需要时重新安装某个软件。该平台默认在绝大多数Dell产品的系统上安装。
漏洞详情
Digital Delivery服务以SYSTEM用户身份运行,其服务名称为DeliveryService,该服务实际上运行的是DeliveryService.exe二进制文件。在用户空间中的DeliveryTray.exe是面向用户的组件,允许用户查看已经安装的应用程序,或重新安装以前购买的应用程序。
从DeliveryTray到DeliveryService的通信是通过Windows Communication Foundation(WCF)命名管道实现的。WCF实质上是在两个终端之间交换数据的标准方法(https://docs.microsoft.com/en-us/dotnet/framework/wcf/whats-wcf)。它允许服务注册一个进程终端,并公开其功能,有点类似于Web服务器的REST API。
在分析过程中,我们可以在Dell.ClientFulfillmentService.Controller.Initialize找到WCF管道的初始化过程:
this._host = WcfServiceUtil.StandupServiceHost(typeof(UiWcfSession), typeof(IClientFulfillmentPipeService), "DDDService");
该过程会调用Dell.NamedPipe.StandupServiceHost:
ServiceHost host = null; string apiUrl = "net.pipe://localhost/DDDService/IClientFulfillmentPipeService"; Uri realUri = new Uri("net.pipe://localhost/" + Guid.NewGuid().ToString()); Tryblock.Run(delegate { host = new ServiceHost(classType, new Uri[] { realUri }); host.AddServiceEndpoint(interfaceType, WcfServiceUtil.CreateDefaultBinding(), string.Empty); host.Open(); }, null, null); AuthenticationManager.Singleton.RegisterEndpoint(apiUrl, realUri.AbsoluteUri);
由此可见,终端已经注册,并且正在监听,由AuthenticationManager单例负责处理请求。一旦收到请求,AuthenticationManager就会将其传递给AuthPipeWorker函数。AuthPipeWorker函数除了其自身的功能外,还会执行以下身份验证:
string execuableByProcessId = AuthenticationManager.GetExecuableByProcessId(processId); bool flag2 = !FileUtils.IsSignedByDell(execuableByProcessId); if (!flag2) { ...
如果请求另一端的进程被经过Dell官方签名的二进制文件支持,那么该请求将被允许,并会建立连接。否则,该请求将被拒绝。
如果将3.1版本和3.5版本进行比较,我们可以发现,这是一个新增的特性。由此可以推断,Dell意识到这是一个潜在的攻击没接。然而,他们采取的缓解措施并不足以保护终端的安全。攻击者能够生成由Dell签署的可执行文件(例如DeliveryTray.exe),随后将特定代码注入到该文件中,来实现对该平台的成功攻击。在注入代码后,攻击者就可以访问特权服务公开的WCF API
终端服务自身是由Dell.NamedPipe实现的,并且目前有10多个不同的函数已经公开,其中包括:
ArchiveAndResetSettings EnableEntitlements EnableEntitlementsAsync GetAppSetting PingTrayApp PollEntitlementService RebootMachine ReInstallEntitlement ResumeAllOperations SetAppSetting SetAppState SetEntitlementList SetUserDownloadChoice SetWallpaper ShowBalloonTip ShutDownApp UpdateEntitlementUiState
Digital Delivery将应用程序安装包称为“Entitlements”,对安装/重装的引用可以用于对当前可用或已安装的包进行操作。
我研究的第一个函数是ReInstallEntitlement,该函数允许用户对已安装的包进行重装。该代码执行以下操作:
private static void ReInstallEntitlementThreadStart(object reInstallArgs) { PipeServiceClient.ReInstallArgs ra = (PipeServiceClient.ReInstallArgs)reInstallArgs; PipeServiceClient.TryWcfCall(delegate { PipeServiceClient._commChannel.ReInstall(ra.EntitlementId, ra.RunAsUser); }, string.Concat(new object[] { "ReInstall ", ra.EntitlementId, " ", ra.RunAsUser.ToString() })); }
上述代码将从请求构建参数,并调用对WCF的调用,该调用将会发送到WCF终端。
ReInstallEntitlement调用有两个参数:Entitlement ID和RunAsUser标志,上述两个参数都是由调用者控制。
在服务器端,Dell.ClientFulfillmentService.Controller负责处理这些函数的实现,OnReInstall负责处理重新安装的过程。在该过程中,会进行完整性检查、包签名验证,同时将由InstallationManager对安装请求进行排队。InstallationManager包含一个作业队列和一个后台线程,负责轮询新的作业,并在接收到安装作业后启动InstallSoftware。
在重新安装包的过程中,软件包会缓存到磁盘中,并准备进行安装。我在这里将会略去几个比较常规的安装步骤,只展现重点的过程。
安装包位于C:\ProgramData\Dell\DigitalDelivery\Downloads\Software\中,首先安装过程会对其进行解压缩,然后执行安装。在我的测试中,安装了Dell Data Protection – Security Tools v1.9.1。如果在Procmon(系统进程管理器)中进行操作,那么就可以看到以下安装过程:
"C:\ProgramData\Dell\Digital Delivery\Downloads\Software\Dell Data Protection _ Security Tools v1.9.1\STSetup.exe" -y -gm2 /S /z"\"CIRRUS_INSTALL, SUPPRESSREBOOT=1\""
此进程的运行用户由可控制的RunAsUser标志确定,如果设置为False,则从%ProgramData%目录中作为SYSTEM运行。
在STSetup进程的进程启动期间,我在procmon中注意到以下内容:
C:\ProgramData\Dell\Digital Delivery\Downloads\Software\Dell Data Protection _ Security Tools v1.9.1\VERSION.dll C:\ProgramData\Dell\Digital Delivery\Downloads\Software\Dell Data Protection _ Security Tools v1.9.1\UxTheme.dll C:\ProgramData\Dell\Digital Delivery\Downloads\Software\Dell Data Protection _ Security Tools v1.9.1\PROPSYS.dll C:\ProgramData\Dell\Digital Delivery\Downloads\Software\Dell Data Protection _ Security Tools v1.9.1\apphelp.dll C:\ProgramData\Dell\Digital Delivery\Downloads\Software\Dell Data Protection _ Security Tools v1.9.1\Secur32.dll C:\ProgramData\Dell\Digital Delivery\Downloads\Software\Dell Data Protection _ Security Tools v1.9.1\api-ms-win-downlevel-advapi32-l2-1-0.dll
值得注意的是,理论上任何系统用户都无法写入父目录%ProgramData%\Dell\Digital Delivery\Downloads\Software中,但包文件夹Dell Data Protection – Security Tools却可以。
这样一来,我们发现系统允许非特权用户将任意文件放入此目录中,就为我们劫持DLL提供了机会。
漏洞利用
针对这一漏洞,利用步骤主要分为以下5步:
1、将DLL放在相应的%ProgramData%软件包目录下;
2、启动运行由Dell签名的可执行文件的新进程;
3、将C#注入到此进程(在用户空间中以无特权的方式运行);
4、将注入的进程连接到WCF命名管道;
5、触发ReInstallEntitlement。
针对步骤4和5,可以采用以下方法执行:
PipeServiceClient client = new PipeServiceClient(); client.Initialize(); while (PipeServiceClient.AppState == AppState.Initializing) System.Threading.Thread.Sleep(1000); EntitlementUiWrapper entitle = PipeServiceClient.EntitlementList[0]; PipeServiceClient.ReInstallEntitlement(entitle.ID, false); System.Threading.Thread.Sleep(30000); PipeServiceClient.CloseConnection();
上面所使用的类,都是从NamedPipe.dll导入的。请注意,我们只选择了第一个可用的包并且进行了重新安装。在实际操作中,攻击者可能需要遍历所有的包,并选择指向此前放置DLL的那个特定的包。
我已经将PoC发布到我的GitHub上:https://github.com/hatRiot/bugs 。此外,Dell还发布了一个安全公告,详情请阅读:https://www.dell.com/support/article/us/en/04/SLN313559 。
时间点
18/05/24 首次将漏洞报告给厂商
18/05/30 Dell要求提供进一步信息
18/06/26 Dell要求提供有关代码复核与修复的最新信息
18/07/06 Dell提供内部进展跟踪ID,并同步当前进展
18/07/24 询问当前进度
18/07/30 Dell确认他们将发布安全建议,同时确定CVE编号
18/08/07 向Dell提醒90天的披露期限
18/08/10 Dell确认可以在8月22日进行披露
18/08/22 公开漏洞详情
参考内容
[0] http://hatriot.github.io/blog/2018/05/17/dell-supportassist-local-privilege-escalation/
[1] https://www.dell.com/learn/us/en/04/flatcontentg/dell-digital-delivery
[2] https://docs.microsoft.com/en-us/dotnet/framework/wcf/whats-wcf
[3] https://github.com/hatRiot/bugs