Dell SupportAssist是一款检查相同软硬件健康的软件,预装在大多数新Dell设备中。研究人员发现dell笔记本电脑安装的第三方软件Dell SupportAssist中存在远程代码执行漏洞。
去年9月,研究人员购买了一台Dell G3 15笔记本电脑,然后研究人员将1TB的硬盘更换为SSD。之后需要重装Windows,然后当研究人员访问dell支持网站时,出现了一个有意思的选项——Detect PC。
点击后,就自动下载和安装了一个驱动。研究人员怀疑Dell通过网站更新了系统中的驱动。
安装后,在后台,SupportAssist Installer创建了一个 SupportAssistAgent和Dell Hardware Support服务。这些服务对应的是.net二进制文件,很容易就可以逆向。
研究人员决定去DELL支持网站看看,研究人员打开Chrome Web Inspector和Network,然后点击Detect Drivers按钮。
该网站向研究人员计算机的8844端口发送请求。用Process Hacker检查该端口说明SupportAssistAgent服务在该端口上有web服务器。Dell做的就是在服务中暴露一个REST API,该服务允许dell网站发送不同的请求来建立通信。Web服务器会响应一个严格的Access-Control-Allow-Origin header为https://www.dell.com,防止其他网站来发送请求。
在web浏览器端,客户端提供了签名机制来认证不同的命令。这些签名是通过到https://www.dell.com/support/home/us/en/04/drivers/driversbyscan/getdsdtoken的请求来生成的,其中也提供了签名过期的时间。在web端点击下载驱动后,会发送请求:
POST http://127.0.0.1:8884/downloadservice/downloadmanualinstall?expires=expiretime&signature=signature Accept: application/json, text/javascript, */*; q=0.01 Content-Type: application/json Origin: https://www.dell.com Referer: https://www.dell.com/support/home/us/en/19/product-support/servicetag/xxxxx/drivers?showresult=true&files=1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36
body为:
[ { "title":"Dell G3 3579 and 3779 System BIOS", "category":"BIOS", "name":"G3_3579_1.9.0.exe", "location":"https://downloads.dell.com/FOLDER05519523M/1/G3_3579_1.9.0.exe?uid=29b17007-bead-4ab2-859e-29b6f1327ea1&fn=G3_3579_1.9.0.exe", "isSecure":false, "fileUniqueId":"acd94f47-7614-44de-baca-9ab6af08cf66", "run":false, "restricted":false, "fileId":"198393521", "fileSize":"13 MB", "checkedStatus":false, "fileStatus":-99, "driverId":"4WW45", "path":"", "dupInstallReturnCode":"", "cssClass":"inactive-step", "isReboot":true, "DiableInstallNow":true, "$$hashKey":"object:175" }]
看似web客户端可以直接请求SupportAssistAgentservice服务来下载和安装程序,研究人员决定分析下使用的命令。
首先,Dell SupportAssist在端口8884, 8883, 8886, 或8885上开启一个web服务器,具体端口与当时可用的端口有关,从8884开始。在请求中,位于HttpListenerServiceFacade的ListenerCallback会调用ClientServiceHandler.ProcessRequest。
ClientServiceHandler.ProcessRequest是基本的web服务器函数,是通过执行完整性检查开始的,以确保请求是来自本地计算机的。
一个重要的完整性检查是ClientServiceHandler.ProcessRequest,尤其是服务器检查来确保referer是来自Dell。
ProcessRequest调用以下函数来确保来自于Dell:中国菜刀
// Token: 0x060000A8 RID: 168 RVA: 0x00004EA0 File Offset: 0x000030A0 public static bool ValidateDomain(Uri request, Uri urlReferrer) { return SecurityHelper.ValidateDomain(urlReferrer.Host.ToLower()) && (request.Host.ToLower().StartsWith("127.0.0.1") || request.Host.ToLower().StartsWith("localhost")) &&request.Scheme.ToLower().StartsWith("http") && urlReferrer.Scheme.ToLower().StartsWith("http"); } // Token: 0x060000A9 RID: 169 RVA: 0x00004F24 File Offset: 0x00003124 public static bool ValidateDomain(string domain) { return domain.EndsWith(".dell.com") || domain.EndsWith(".dell.ca") || domain.EndsWith(".dell.com.mx") || domain.EndsWith(".dell.com.br") || domain.EndsWith(".dell.com.pr") || domain.EndsWith(".dell.com.ar") || domain.EndsWith(".supportassist.com"); }
围绕过Referer/Origin检查,有以下选项:
· 在Dell网站找到扩展脚本漏洞
· 找到子域接管漏洞
· 确保请求是来自本地程序的
· 生成一个随机子域名,使用外部机器来劫持受害者。然后,当受害者请求 [random].dell.com,就响应服务器。
最后,研究人员决定选择第4种方案。在确认了请求的Referer/Origin后,ProcessRequest会发送请求到对应的GET, POST, OPTIONS函数。
研究人员在了解了Dell SupportAssist的工作原理后,研究人员拦截了来自Dell支持网站的不同类型的请求。
首先,web站点尝试用前面提到的服务端口连接到服务方法isalive,来检测SupportAssist。它会传递参数Signature和“Expires”。然后研究人员逆向了浏览器的JS端代码,发现:天空彩
1. 首先,浏览器创建一个到
https://www.dell.com/support/home/us/en/04/drivers/driversbyscan/getdsdtoken的请求,来获取最新的Token或签名。终端也提供Expires token来解决签名问题。
2. 然后,浏览器向每个服务端口发送形如http://127.0.0.1:[SERVICEPORT]/clientservice/isalive/?expires=[EXPIRES]&signature=[SIGNATURE]的请求。
3. SupportAssist客户端在正确的端口到达时会响应,形如:
{ "isAlive": true, "clientVersion": "[CLIENT VERSION]", "requiredVersion": null, "success": true, "data": null, "localTime": [EPOCH TIME], "Exception": { "Code": null, "Message": null, "Type": null }}
4. 浏览器看到后,会使用当时的端口继续发送请求。
下面是agent暴露的一些方法:
· clientservice_getdevicedrivers – 获取可用更新
· diagnosticsservice_executetip – 获取guid并提供给PC Doctor服务(Dell Hardware Support)
· downloadservice_downloadfiles – 下载文件的JSON数组
· clientservice_isalive – 作为心跳,返回关于agent的基本信息
· clientservice_getservicetag – 获取服务 tag.
· localclient_img – 连接到SignalR (Dell Hardware Support).
· diagnosticsservice_getsysteminfowithappcrashinfo – 获取含有奔溃信息的系统信息
· clientservice_getclientsysteminfo – 获取关于系统信息和系统健康信息的设备信息
· diagnosticsservice_startdiagnosisflow -用来诊断系统上的问题
· downloadservice_downloadmanualinstall – 下载文件但不执行
· diagnosticsservice_getalertsandnotifications – 获取暂停的告警和通知
· diagnosticsservice_launchtool – 启动诊断工具
· diagnosticsservice_executesoftwarefixes – 运行修复UI,执行特定动作。
· downloadservice_createiso – 下载ISO.
· clientservice_checkadminrights – 检查agent是否是特权的
· diagnosticsservice_performinstallation – 更新SupportAssist.
· diagnosticsservice_rebootsystem – 重启系统.
· clientservice_getdevices – 获取系统设备信息
· downloadservice_dlmcommand – 检查下载状态或取消下载
· diagnosticsservice_getsysteminfo – 调用PC Doctor上的GetSystemInfo
· downloadservice_installmanual – 安装之前用downloadservice_downloadmanualinstall下载的文件
· downloadservice_createbootableiso – 下载可启动的iso.
· diagnosticsservice_isalive – 心跳检查.
· downloadservice_downloadandautoinstall – 下载文件并执行
· clientservice_getscanresults – 获取驱动扫描结果
· downloadservice_restartsystem – 重启系统
研究人员注意到一个方法downloadservice_downloadandautoinstall,该方法会从特定URL来下载文件,然后运行。该方法当用户需要安装特定驱动时由浏览器运行的。
1、在找到需要更新的驱动后,浏览器会发送一个POST请求到http://127.0.0.1:[SERVICE PORT]/downloadservice/downloadandautoinstall?expires=[EXPIRES]&signature=[SIGNATURE]
2、浏览器会发送含有以下JSON结构的请求:
[ { "title":"DOWNLOAD TITLE", "category":"CATEGORY", "name":"FILENAME", "location":"FILE URL", "isSecure":false, "fileUniqueId":"RANDOMUUID", "run":true, "installOrder":2, "restricted":false, "fileStatus":-99, "driverId":"DRIVER ID", "dupInstallReturnCode":0, "cssClass":"inactive-step", "isReboot":false, "scanPNPId":"PNP ID", "$$hashKey":"object:210" }]
3、在执行基本的完整性检查后,ClientServiceHandler.ProcessRequest会发送ServiceMethod和传递给ClientServiceHandler.HandlePost的参数。
4、ClientServiceHandler.HandlePost首先将所有参数都放在一个数组中,然后调用ServiceMethodHelper.CallServiceMethod.
5、ServiceMethodHelper.CallServiceMethod函数作为一个分发函数,会调用ServiceMethod方法。downloadandautoinstall方法如下所示:
if (service_Method == "downloadservice_downloadandautoinstall") { string files5 = (arguments != null && arguments.Length != 0 && arguments[0] != null) ? arguments[0].ToString() : string.Empty; result = DownloadServiceLogic.DownloadAndAutoInstall(files5, false); }
该方法调用DownloadServiceLogic.DownloadAutoInstall,并提供JSON payload中发送的文件。
6、DownloadServiceLogic.DownloadAutoInstall作为DownloadServiceLogic._HandleJson的封装。
7、DownloadServiceLogic._HandleJson反序列化含有要下载的文件列表的JSON payload,并做如下的完整性检查:
foreach (File file in list) { bool flag2 = file.Location.ToLower().StartsWith("http://"); if (flag2) { file.Location = file.Location.Replace("http://", "https://"); } bool flag3 = file != null && !string.IsNullOrEmpty(file.Location) && !SecurityHelper.CheckDomain(file.Location); if (flag3) { DSDLogger.Instance.Error(DownloadServiceLogic.Logger, "InvalidFileException being thrown in _HandleJson method"); throw new InvalidFileException(); } } DownloadHandler.Instance.RegisterDownloadRequest(CreateIso, Bootable, Install, ManualInstall, list);
上面的代码对每个文件都会进行循环,检查文件URL是否是以http://开头的,如果是就用https://替换,并检查URL是否与Dell下载服务器列表匹配:
public static bool CheckDomain(string fileLocation) { List<string> list = new List<string> { "ftp.dell.com", "downloads.dell.com", "ausgesd4f1.aus.amer.dell.com" }; return list.Contains(new Uri(fileLocation.ToLower()).Host); }
最后,如果所有检查都通过,获取的文件就发送给DownloadHandler.RegisterDownloadRequest,此时SupportAssist会下载并以administrator运行。
PoC视频见https://www.youtube.com/embed/0cTfnZ04jgQ
PoC视频中的dellrce.html文件源代码为:
<h1>CVE-2019-3719</h1><h1>Nothing suspicious here... move along...</h1><iframe src="http://www.dellrce.dell.com" style="width: 0; height: 0; border: 0; border: none; position: absolute;"></iframe>
PoC代码见https://github.com/D4stiny/Dell-Support-Assist-RCE-PoC