[CVE-2019-3719] Phân tích và POC Lỗ hổng khai thác chiếm quyền điều khiển máy tính DELL từ xa. | remote code execution on most Dell computer (Phần 1)
Bài đăng này đã không được cập nhật trong 5 năm
1. Tổng quan
Nếu anh em nào đó đang sử dụng máy tính DELL mà lâu lâu rồi chưa update thì hãy cẩn thận đấy... Sau bài viết này các bạn có thể trở thành những "nạn nhân" cho các anh em khác thử nghiệm đấy.
Cụ thể, một người nghiên cứu bảo mật 17 tuổi tên là Bill Demirkapi đã phát hiện ra lổ hổng bảo mật nghiêm trọng này trên các thiết bị của Dell. Lổ hổng này cho phép tin tặc có thể điều khiển máy tính nạn nhân từ xa thông qua phần mềm Dell SupportAssist.
2. Phát hiện và phân tích luồng xử lý
2.1. Con đường phát hiện
Khi tiến hành cài đặt các driver cho máy tính khi người dùng truy cập vào trang hỗ trợ của Dell chúng ta có các tùy chọn sau để cho hệ thống có thể nhận biết được thiết bị của bạn và từ đó đưa ra các file driver phù hợp.
Ở đây có tùy chọn Detect PC . Vậy nó sẽ làm thế nào để phát hiện PC của chúng ta. Khi nhấn vào tùy chọn đó. Nó sẽ đưa chúng ta đến trang yêu cầu cài đặt phần mềm này:
Đây là một chương trình tự động cài đặt driver cho thiết bị dell. Mặc dù nó là một tính năng tiện lợi, nhưng nó có vẻ nguy hiểm. Điều rất đáng ngờ là Dell tuyên bố có thể cập nhật driver thông qua một trang web.
Sau khi cài đặt xong, nó tạo ra 2 dịch vụ chạy trên thiết bị là SupportAssistAgent và Dell Hardware Support. Quay lại website vừa nãy. . Mở dev tools của Chrome và vào tabs Network. Khi ta click vào Detect Drivers.
Ở devtool tabs Network ta thấy:
Thầy rằng website này đã tạo các request đến localhost với port 8884. Sử dụng process hacker kiểm tra dịch vụ trên port 8884, thấy rằng Support Assist Agent đang hoạt động trên port đó như là 1 dịch vụ web.
2.2 Bước đầu phân tích
Qua đây thấy rằng, Những gì Dell đang làm là đưa ra một loại API REST trong dịch vụ của họ, cho phép liên lạc từ trang web của Dell để thực hiện các yêu cầu khác nhau như thu thập thông tin hệ thống, tải xuống một phần mềm từ máy chủ và cài đặt nó lên hệ thống. Dịch vụ web này được bảo vệ bằng respone header Access-Control-Allow-Origin chỉ nhận lệnh thực thi từ "dell.com" hoặc các subdomain của Dell mà thôi.
Về phía trình duyệt web, khách hàng đã cung cấp một chữ ký để xác thực các lệnh khác nhau. Những chữ ký này được tạo bằng cách gửi yêu cầu tới https://www.dell.com/support/home/us/en/04/drivers/driversbyscan/getdsdtoken và cũng cung cấp khi chữ ký hết hạn. Sau khi nhấn Download Driver, thấy rằng request này rất "hay ho":
- Request này đã chuyển hướng lệnh thực thi sang cho Support Assist Agent để download và cài đặt chương trình lên hệ thống.
- Khi bắt đầu, Dell SupportAssist khởi động một máy chủ E web (System.Net.HttpListener) trên một trong ba cổng 8884, 8883, 8886 hoặc cổng 8885. Cổng này phụ thuộc vào tùy chọn nào có sẵn, bắt đầu từ 8884. Theo yêu cầu, ListenerCallback nằm trong HttpListenerServiceFacade gọi ClientServiceHandler.ProcessRequest
- ClientServiceHandler.ProcessRequest, base web server function, bắt đầu bằng cách thực hiện kiểm tra tính toàn vẹn, ví dụ như đảm bảo yêu cầu đến từ local machine và nhiều kiểm tra khác.
- Sau 1 số kỹ thuật dịch ngược, thấy rằng kiểm tra tính toàn vẹn quan trọng nằm trong ClientServiceHandler.ProcessRequest, cụ thể là chỗ máy chủ kiểm tra referrer để bảo đảm đến từ Dell. ProcessRequest gọi chức năng sau để đảm bảo rằng yêu cầu đến từ 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");
}
Vấn đề với chức năng trên là thực tế nó kiểm tra chưa chặt chẽ và cung cấp cho attacker rất nhiều tùy chọn để tấn công. Để bypass qua kiểm tra này chúng ra có vài tùy chọn:
- Tìm lỗ hổng Cross Site Scripting trong bất kỳ trang web nào của Dell (phải tìm một lỗ hổng trên các trang web được chỉ định cho SupportAssist). Rất khó khăn.
- Tìm một lỗ hổng Subdomain Takeover
- Thực hiện yêu cầu từ một local program.
- Tạo một tên miền phụ ngẫu nhiên và sử dụng một máy bên ngoài để DNS Hijack nạn nhân. Sau đó, khi nạn nhân yêu cầu [xxx] .dell.com, ta sẽ respone với máy chủ của chúng ta.
Cuối cùng, phương án 4 là khả thi nhất.
2.3 Phát hiện điểm yếu trong logic sử lý
Trong quá trình phân tích, phát hiện ra một số vấn đề sau. Lúc đầu, trang web cố gắng phát hiện SupportAssist bằng cách lặp qua các cổng dịch vụ đã nói ở trên và kết nối với Service Method “isalive”. Điều thú vị là nó đã vượt qua “Signature” parameter và một “Expires” parameter. Để tìm hiểu thêm, phân tích JS ta được một số vấn đề sau:
- Đầu tiên, trình duyệt đưa ra yêu cầu https://www.dell.com/support/home/us/en/04/drivers/driversbyscan/getdsdtoken và nhận được Token mới nhất, hoặc các chữ ký [Signature] mà đã nói trước đó. Cuối cũng cung cấp mã thông báo Hết hạn sử dụng "Expires token". Điều này giải quyết vấn đề chữ ký.
- Tiếp theo, trình duyệt đưa ra yêu cầu cho mỗi cổng dịch vụ với kiểu như sau:
http://127.0.0.1:[SERVICEPORT[/clentservice/aluive/?Exires=[EXPIRES[&signature=[SIGNATURE]
. - Sau đó, ứng dụng khách Support Assist phản hồi khi đạt đến cổng dịch vụ phù hợp, với kiểu như sau:
{
"isAlive": true,
"clientVersion": "[CLIENT VERSION]",
"requiredVersion": null,
"success": true,
"data": null,
"localTime": [EPOCH TIME],
"Exception": {
"Code": null,
"Message": null,
"Type": null
}
}
- Khi trình duyệt thấy điều này, nó sẽ tiếp tục với các yêu cầu tiếp theo sử dụng cổng dịch vụ hiện được xác định.
Sau một thời gian lần mò, đã tìm ra được một số dịch vụ/câu lệnh "hay ho":
clientservice_getdevicedrivers - Grabs available updates.
diagnosticsservice_executetip - Takes a tip guid and provides it to the PC Doctor service (Dell Hardware Support).
downloadservice_downloadfiles - Downloads a JSON array of files.
clientservice_isalive - Used as a heartbeat and returns basic information about the agent.
clientservice_getservicetag - Grabs the service tag.
localclient_img - Connects to SignalR (Dell Hardware Support).
diagnosticsservice_getsysteminfowithappcrashinfo - Grabs system information with crash dump information.
clientservice_getclientsysteminfo - Grabs information about devices on system and system health information optionally.
diagnosticsservice_startdiagnosisflow - Used to diagnose issues on system.
downloadservice_downloadmanualinstall - Downloads a list of files but does not execute them.
diagnosticsservice_getalertsandnotifications - Gets any alerts and notifications that are pending.
diagnosticsservice_launchtool - Launches a diagnostic tool.
diagnosticsservice_executesoftwarefixes - Runs remediation UI and executes a certain action.
downloadservice_createiso - Download an ISO.
clientservice_checkadminrights - Check if the Agent privileged.
diagnosticsservice_performinstallation - Update SupportAssist.
diagnosticsservice_rebootsystem - Reboot system.
clientservice_getdevices - Grab system devices.
downloadservice_dlmcommand - Check on the status of or cancel an ongoing download.
diagnosticsservice_getsysteminfo - Call GetSystemInfo on PC Doctor (Dell Hardware Support).
downloadservice_installmanual - Install a file previously downloaded using downloadservice_downloadmanualinstall.
downloadservice_createbootableiso - Download bootable iso.
diagnosticsservice_isalive - Heartbeat check.
downloadservice_downloadandautoinstall - Downloads a list of files and executes them.
clientservice_getscanresults - Gets driver scan results.
downloadservice_restartsystem - Restarts the system.
Thứ khiến chúng ta quan tâm là downloadservice_downloadandautoinstall nó sẽ tải tệp từ một được chỉ định và sau đó chạy nó. Phương pháp này được chạy bởi trình duyệt khi người dùng cần cài đặt một số trình điều khiển nhất định cần được cài đặt tự động. Thông qua đây chúng ta có thể bắt nạn nhận tải xuống và thực thi 1 file độc hại...
2.4 Phân tích quá trình thực thi việc tự động tải về và thực thi (downloadservice_downloadandautoinstall)
- Sau khi tìm thấy trình điều khiển nào cần cập nhật, trình duyệt sẽ tạo một yêu cầu POST cho tới
http://127.0.0.1:[SERVICEPORT]/downloadservice/downloadandautoinstall?expires=[EXPIRES]&signature=[SIGNATURE]
- Trình duyệt gửi yêu cầu có cấu trúc JSON sau đây:
[
{
"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"
}
]
- Sau khi thực hiện kiểm tra tính toàn vẹn cơ bản mà đã thảo luận trước đó, ClientServiceHandler.ProcessRequest sẽ gửi ServiceMethod và các tham số đã truyền cho ClientServiceHandler.HandlePost.
- ClientServiceHandler.HandlePost trước tiên đặt tất cả các tham số vào một mảng, sau đó gọi ServiceMethodHelper.CallServiceMethod.
- ServiceMethodHelper.CallServiceMethod hoạt động như một chức năng điều phối và gọi hàm được cung cấp ServiceMethod. Đây là phương thức downloadandautoinstallinstall:
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 hoạt động như một trình wrapper (i.e handling exceptions) cho DownloadServiceLogic._HandleJson.
- DownloadServiceLogic._HandleJson sẽ deserializes payload JSON chứa danh sách các tệp cần tải xuống và thực hiện kiểm tra tính toàn vẹn sau đây
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);
Đoạn mã trên lặp lại qua từng tệp và kiểm tra xem URL tệp chúng ta cung cấp bắt đầu bằng http: // hay không? (nếu có, thế bằng https: //) và kiểm tra xem URL có khớp với danh sách tải xuống của Dell? (không phải tất cả subdomain):
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);
}
Cuối cùng, nếu tất cả các kiểm tra này vượt qua, các tệp sẽ được gửi đến DownloadHandler.RegisterDoadRequest và Support Assist sẽ tải xuống và chạy các tệp với tư cách Quản trị viên.
Vậy là thông qua đây ta có thể tiến hành khai thác.( các bạn chờ phần 2 nhá )
3. Cách khai thác
(vui lòng đón đọc phần 2)
4. Tổng kết đánh giá và phương pháp phòng tránh
All rights reserved