HeadlWin: Vì sao Secure Boot và Hardware Root of Trust lại quan trọng

HeadlWin: Vì sao Secure Boot và Hardware Root of Trust lại quan trọng 

     Vì nhiều lý do chính đáng khác nhau, người dùng thường tìm đến các giải pháp phần mềm nhằm cung cấp mức độ riêng tư và bảo mật cao để tự bảo vệ bản thân trên môi trường trực tuyến. Tuy nhiên, nhiều người sử dụng các giải pháp bảo mật này lại không nhận ra rằng nếu hệ thống nền tảng bên dưới bị compromise, thì toàn bộ khả năng bảo mật và quyền riêng tư mà phần mềm mang lại gần như sẽ bị vô hiệu hóa hoàn toàn — khiến người dùng tưởng rằng mình đang được bảo vệ nhưng thực tế lại đang gặp rủi ro. Trong những năm gần đây, ngày càng có nhiều sự chú ý hướng tới Hardware Root of Trust vulnerabilities khi ngày càng nhiều hệ thống hỗ trợ Secure Boot và các công nghệ liên quan. Các lỗ hổng dạng này thường khá “khó tiếp cận” vì hiếm khi xuất hiện các đoạn mã proof-of-concept trực tiếp minh họa khả năng khai thác. Ngay cả khi PoC được công bố, cách trình bày thường mang nặng tính kỹ thuật và không phải lúc nào cũng thể hiện rõ một cuộc tấn công hoàn chỉnh ngoài thực tế. Do đó, ngay cả với các software engineer hoặc security professional giàu kinh nghiệm, việc hiểu được mức độ ảnh hưởng nghiêm trọng của việc compromise Hardware Root of Trust đôi khi vẫn không hề đơn giản. Chúng tôi đã chọn đây làm mục tiêu cho một dự án nghiên cứu: chứng minh vì sao Hardware Root of Trust lại quan trọng, cũng như cách mà việc compromise thành phần này có thể làm suy yếu bảo mật của toàn bộ nền tảng hệ thống. Hardware Root of Trust được thiết kế nhằm bảo vệ hệ điều hành khỏi các hành vi can thiệp độc hại ở mức thấp (low-level malicious tampering) bằng cách cung cấp các đảm bảo mật mã học (cryptographic guarantees) cho firmware, bootloader và kernel của hệ điều hành.

(Hình 1: Trang chủ của Tails Website)

     Để đạt được mục tiêu này, chúng tôi đã lựa chọn một đối tượng nghiên cứu khá đặc biệt: bản phân phối Linux Tails [1]. Thử nghiệm được thực hiện trên Tails 6.16 — phiên bản mới nhất của Tails tại thời điểm bài viết này được thực hiện. Tails OS được thiết kế như một hệ điều hành tạm thời (ephemeral operating system), được cài đặt trên USB stick. USB này sẽ được cắm vào máy tính mục tiêu và hệ thống sẽ boot trực tiếp từ USB. Trong quá trình cài đặt, người dùng có thể cấu hình một phân vùng dữ liệu persistent sử dụng filesystem Linux LUKS. Phân vùng persistent này được bảo vệ bằng passphrase mà người dùng phải nhập trong các lần khởi động tiếp theo để truy cập dữ liệu đã lưu. Phân vùng chứa hệ điều hành được thiết kế ở trạng thái tĩnh (static) và được mount dưới chế độ chỉ đọc (read-only) trong quá trình người dùng sử dụng hệ thống. Toàn bộ dữ liệu persistent sẽ được ghi vào phân vùng LUKS; người dùng không thể ghi dữ liệu trực tiếp vào phân vùng hệ điều hành trong lúc tương tác với OS. Tails được phát triển dành cho các tình huống yêu cầu mức độ riêng tư và bảo mật cao — chẳng hạn như các nhà hoạt động đối lập trong các chế độ kiểm soát nghiêm ngặt (dissidents in repressive governments), hoặc các môi trường mà việc bảo vệ danh tính và dữ liệu là đặc biệt quan trọng.

(Hình 2: Ảnh chụp chức năng “Amnesia” của Tails)

     Mô hình đe dọa (threat model) trong môi trường lab của chúng tôi giả định rằng attacker kiểm soát hoàn toàn máy tính host và có khả năng chỉnh sửa EFI firmware của hệ thống. EFI Firmware chịu trách nhiệm khởi tạo các thành phần phần cứng của máy tính trước khi hệ điều hành được nạp vào bộ nhớ và bắt đầu thực thi. Thuật ngữ này thường được sử dụng gần tương đương với BIOS, tuy nhiên về mặt kỹ thuật, EFI chính là thế hệ kế nhiệm của BIOS truyền thống. Trong kịch bản này, chúng tôi giả định attacker không có quyền kiểm soát USB drive chứa Tails, bởi trong một cuộc tấn công thực tế, attacker sẽ không thể chỉnh sửa nội dung USB nếu USB đó chưa từng được cắm vào máy host đã bị compromise.

     Mặc dù Tails được xây dựng với trọng tâm là bảo mật và quyền riêng tư, các maintainer của dự án lại quyết định không triển khai Secure Boot cho bản phân phối này. Điều này khá đáng chú ý, bởi Debian — nền tảng mà Tails được phát triển dựa trên — vốn đã hỗ trợ Secure Boot từ lâu. Trên thực tế, đây lại trở thành một lỗ hổng nghiêm trọng trong mô hình bảo mật của Tails OS; và dường như chính các maintainer của Tails cũng nhận thức được vấn đề này. Trong trang “Warnings” [2], nhóm phát triển đã lưu ý rằng:

Tails không phải lúc nào cũng có thể bảo vệ bạn trong các trường hợp sau:

  • Cài đặt Tails từ một máy tính đã bị nhiễm độc

  • Chạy Tails trên một hệ thống có BIOS, firmware hoặc phần cứng đã bị compromise

(Hình 3: Ảnh chụp trang cảnh báo trên website Tails)

Lấy đây làm điểm khởi đầu, chúng tôi quyết định chứng minh mức độ ảnh hưởng của việc thiếu Hardware Root of Trust đối với hệ điều hành Tails.

     Bước đầu tiên của dự án là xây dựng một môi trường Tails được ảo hóa (virtualized environment). Chúng tôi lựa chọn môi trường ảo hóa nhằm giảm độ phức tạp của dự án, bởi làm việc trực tiếp trên phần cứng thật sẽ tốn rất nhiều thời gian và công sức. Môi trường ảo hóa dễ thao tác hơn đáng kể, trong khi vẫn có khả năng minh họa rõ tác động của lỗ hổng dù không chạy trên phần cứng vật lý thực tế.

     Môi trường Tails ảo hóa của chúng tôi hoạt động trên Linux host sử dụng QEMU [3] kết hợp với Open Virtual Machine Firmware (OVMF) [4] làm triển khai UEFI.

QEMU mặc định sử dụng OVMF đối với các host hỗ trợ EFI và cung cấp tham số -bios, cho phép chỉ định đường dẫn tới một phiên bản OVMF tùy chỉnh. Thông qua tham số này, chúng tôi đã biên dịch một phiên bản OVMF riêng có tích hợp DXE Driver do chúng tôi kiểm soát. Trong môi trường phần cứng thực tế, attacker thường không thể biên dịch lại toàn bộ firmware volume từ source code. Tuy nhiên, vẫn có thể chỉnh sửa một EFI image đã được compile sẵn để chèn thêm DXE driver bằng công cụ UEFITool [5]. Để thực hiện điều này, cần sử dụng UEFITool phiên bản 0.28 kết hợp với file DXE driver định dạng .ffs (đây là file trung gian được tạo ra trong quá trình xây dựng firmware volume).

     Trong quá trình cài đặt Tails, hệ điều hành sẽ tạo một EFI System Partition (ESP) chứa bootloader GRUB2 và initial RAM disk (initrd) mà bootloader sẽ chuyển quyền thực thi tới trong quá trình khởi động. Một điểm cực kỳ quan trọng là: trên hệ thống bật Secure Boot, bootloader GRUB2 (vốn chỉ là một EFI application) sẽ được EFI firmware đo lường (measured) và xác minh dựa trên cryptographic hash. Nếu hash của GRUB2 không khớp → EFI firmware sẽ từ chối thực thi bootloader. Nếu hash hợp lệ → GRUB2 sẽ được chạy và tiếp tục xác thực initial RAM disk dựa trên hash do vendor chỉ định. Tương tự như cách EFI firmware xác minh chữ ký của ứng dụng GRUB2 EFI, chính GRUB2 cũng sẽ xác minh chữ ký của initial RAM disk. Nếu signature hash không khớp → GRUB2 sẽ không chuyển quyền thực thi sang initial RAM disk.

OVMF có thể được biên dịch thủ công bằng source code EDK2 [6]. Sau khi clone mã nguồn EDK2 từ Git repository, chúng tôi tạo symbolic link tới thư mục chứa source code DXE Driver của mình vào bên trong repository và thêm tham chiếu tới driver đó trong các file .DSC.FDF. .DSC là platform description file .FDF là firmware description file. Sau đó, chúng tôi biên dịch lại EDK2 với DXE driver đã được chèn vào, kết quả tạo ra một instance OVMF tùy chỉnh có chứa DXE driver do chúng tôi kiểm soát.

     DXE driver của chúng tôi được đặt tên vui là AtlBkDxe (Aruba Threat Labs BootKit DXE) — thực hiện nhiều thao tác quan trọng để khởi đầu chuỗi khai thác (exploit chain). Đầu tiên và quan trọng nhất, DXE driver này khởi tạo các network interface được gắn với hệ thống. Trên phần cứng thực tế, đây thường sẽ là một Ethernet NIC; còn trong môi trường ảo hóa của chúng tôi, đó là một virtualized ethernet adapter được gắn vào virtual PCI bus. Ở phía hypervisor host, chúng tôi sử dụng cơ chế user-mode networking của QEMU để chuyển tiếp lưu lượng mạng từ máy ảo ra phần còn lại của hệ thống mạng thông qua network adapter của hypervisor. Một điểm đáng chú ý là mặc dù chúng tôi lựa chọn Ethernet interface để đơn giản hóa thử nghiệm, nhiều triển khai EFI trên phần cứng thực tế hiện nay cũng hỗ trợ Wi-Fi bên cạnh Ethernet. Điều đó có nghĩa là nếu attacker biết WPA2 PSK của mạng WLAN mà mục tiêu đang sử dụng, cuộc tấn công vẫn có thể được thực hiện thông qua Wi-Fi. Nói cách khác, cuộc tấn công này không chỉ giới hạn ở Ethernet interface trong môi trường thực tế.

     Sau khi khởi tạo network interface, DXE driver độc hại sẽ thực hiện quá trình DHCP handshake để nhận địa chỉ IP từ mạng. Khi quá trình này thành công, hệ thống đã sẵn sàng tạo lưu lượng mạng IP-routed cho các bước tiếp theo của cuộc tấn công.

     Khi đã có địa chỉ IP, DXE driver có thể gửi HTTP request tới một host có thể định tuyến IP (IP routable host). Các phiên bản EDK2 hiện đại đã đơn giản hóa việc tạo HTTP request đến mức chúng tôi không cần tự xử lý DNS resolution. Chúng tôi chỉ cần truyền một URL cho HttpDxe driver và driver này sẽ tự động xử lý việc phân giải DNS hostname sang địa chỉ IP, bao gồm cả việc gửi và nhận các UDP packet cần thiết tới DNS server thông qua network interface đã cấu hình. Một chi tiết bên lề là chúng tôi thực hiện HTTP request dưới dạng cleartext (không sử dụng TLS/HTTPS) nhằm đơn giản hóa quá trình thử nghiệm. EDK2 thực tế có hỗ trợ TLS/HTTPS thông qua một custom Certificate Authority bundle có thể được compile trực tiếp vào firmware. Tuy nhiên, vì web server do attacker kiểm soát trong môi trường lab của chúng tôi sử dụng self-signed certificate và không public ra Internet, nên chúng tôi quyết định không triển khai thêm các bước cần thiết để hỗ trợ HTTPS. HTTP request này là một GET request gửi tới attacker-controlled web server nhằm tải về một file được hardcode với tên: initrd.img DXE driver sau đó tiếp tục xử lý lưu lượng TCP cho tới khi file được tải xuống hoàn tất. Sau khi quá trình tải file kết thúc, DXE driver sẽ mở EFI System Partition (ESP) — vốn là một phân vùng FAT32 — và ghi đè file: /live/initrd.img bằng file initrd.img vừa được tải từ web server do attacker kiểm soát.

     Như bạn có thể đoán được, file initrd.img được tải về từ web server của attacker thực chất là một phiên bản đã bị chỉnh sửa của file /live/initrd.img nằm trên ESP. File /live/initrd.img gốc bao gồm ba CPIO archive: Hai archive đầu tiên chứa CPU microcode dành cho processor Intel và AMD Archive thứ ba được nén bằng XZ và chứa filesystem thực tế của initial RAM disk. Chúng tôi sử dụng công cụ binwalk [7] để giải nén (decompress) và trích xuất (extract) các CPIO archive này.

(Hình 4: Kết quả Binwalk đối với file /live/initrd.img)

     Các file mà chúng tôi thêm vào bao gồm: một system job description file, một ứng dụng C được statically compiled và một kernel module Script /init sẽ di chuyển application và system job tới thư mục: /usr/bin và chuyển system service definition file tới /etc/systemd/system/ trên target root filesystem. Ngoài ra, chúng tôi cũng tạo một symbolic link tới systemd service definition file trong thư mục: /etc/systemd/system/multi-user.target.wants/ để cho phép systemd tự động thực thi ứng dụng C đã được statically compiled trong quá trình boot hệ thống. Cuối cùng, các chỉnh sửa trong script /init sẽ nạp (load) custom kernel module vào kernel-space bằng lệnh: insmod. Không cần phải sao chép file kernel module sang target root filesystem.

     Khi GRUB2 chuyển quyền thực thi sang initial RAM disk, một shell script tại đường dẫn: /init bên trong initial RAM disk sẽ được thực thi. Đây là file duy nhất mà chúng tôi trực tiếp chỉnh sửa trong initial RAM disk filesystem, mặc dù chúng tôi cũng bổ sung thêm một số file mới khác (bao gồm system job description file, ứng dụng C statically compiled và kernel module). Các chỉnh sửa trong /init về bản chất sẽ sao chép các file mà chúng tôi thêm vào từ initial RAM disk sang target root filesystem. Cần nhớ rằng initial RAM disk filesystem là một dạng filesystem “pre-OS”, chịu trách nhiệm thiết lập toàn bộ Linux userspace filesystem trước khi thực thi: pivot_root hoặc switch_root để chuyển sang target root filesystem — chính là môi trường mà người dùng sẽ tương tác sau khi hệ thống hoàn tất quá trình khởi động.

(Hình 5: systemd service definition file)

     Mặc dù target root filesystem được mount dưới chế độ chỉ đọc (read-only), initial RAM disk thì không bị giới hạn như vậy. Điều này có nghĩa là trước khi: pivot_root được thực thi, chúng tôi vẫn có thể chỉnh sửa target root filesystem vì tại thời điểm đó nó vẫn chưa được mount làm root filesystem chính thức.

     Ứng dụng C được statically compiled mà chúng tôi triển khai thực chất là một user-space keylogger. Ứng dụng này đọc các thao tác bàn phím từ thiết bị: /dev/input/event0 và lưu các phím bấm vào một buffer trong bộ nhớ. Keylogger sau đó cố gắng mở một kết nối TCP tới attacker-controlled server trên port: 4444. Nếu kết nối thành công → toàn bộ key press trong buffer sẽ được gửi qua kết nối TCP tới server của attacker. Nếu không thể kết nối → ứng dụng sẽ chờ 1 giây rồi thử lại liên tục cho đến khi thiết lập được kết nối TCP. Sau khi TCP connection được thiết lập, mọi sự kiện nhấn phím (key press events) sẽ được gửi trực tiếp tới attacker thông qua kết nối đó.

     Lý do chúng tôi cần buffer các key press event là bởi network interface của Tails chưa được khởi tạo cho tới khi người dùng nhập LUKS passphrase. Tuy nhiên, systemd job của chúng tôi đã được thực thi từ trước thời điểm người dùng nhập passphrase. Điều này cho phép attacker ghi nhận toàn bộ thao tác bàn phím, dù ở thời điểm đó chưa thể gửi dữ liệu ra remote server. Ngay sau khi người dùng nhập LUKS passphrase, Tails sẽ khởi tạo network interface. Khi đó ứng dụng C mới có thể thiết lập TCP connection và gửi toàn bộ keystroke đã thu thập được tới attacker-controlled server.

     Cuối cùng, chúng tôi cũng đã thực hiện việc cross-compile một Linux Kernel Module (LKM) dành riêng cho phiên bản Linux Kernel của Tails - cụ thể là kernel version: 6.8.140. Để thực hiện điều này, chúng tôi sử dụng buildroot [8]. Mặc dù buildroot thường được dùng trong các dự án Embedded Linux, chúng tôi vẫn có thể tận dụng nó để cross-compile một LKM cho Tails. Tuy nhiên, do giới hạn về thời gian, chúng tôi chưa thể xây dựng nhiều chức năng phức tạp cho kernel module này. Cuối cùng, mục tiêu chính chỉ là chứng minh rằng chúng tôi có khả năng thực thi mã trong kernel-space bằng cách chạy một thông điệp printk tùy chỉnh.

(Hình 6: Ảnh chụp source code của Custom Kernel Module)

     Linux Kernel Module (LKM) chứa một chuỗi định danh được gọi là: vermagic. Kernel đang chạy sẽ xác minh chuỗi này có khớp với cấu hình hiện tại của Linux Kernel hay không trước khi cho phép module được thực thi trong kernel-space. Nếu chuỗi vermagic không khớp, kernel sẽ từ chối load module. Để biên dịch custom kernel module của mình, chúng tôi cần chính xác cấu hình kernel mà Tails đang sử dụng. May mắn cho chúng tôi là các developer của Tails đã để lại file cấu hình kernel này trong target root filesystem tại thư mục: /boot

     Tuy nhiên, ngay cả khi đã có đúng kernel configuration, chuỗi vermagic của Tails vẫn không khớp vì Tails sử dụng một giá trị đặc thù của Debian. Điều này dẫn tới việc dù chúng tôi đã sử dụng chính xác cấu hình kernel của Tails, giá trị vermagic tạo ra vẫn sẽ luôn sai lệch so với kernel thực tế. Kết quả là chúng tôi buộc phải viết một shell script nhỏ để chỉnh sửa thủ công chuỗi vermagic này.

(Hình 7: Script chỉnh sửa chuỗi Vermagic)

     Tails cho phép người dùng thiết lập mật khẩu administrator theo từng phiên làm việc (per-session administrator password) trước khi hệ điều hành hoạt động hoàn chỉnh. Nếu mật khẩu này được thiết lập, người dùng có thể đăng nhập vào root shell và kiểm tra log kernel bằng lệnh: dmesg. Khi thực hiện điều đó, chúng tôi có thể xác nhận rằng kernel module đã được load thành công và câu lệnh: printk tùy chỉnh của chúng tôi đã được thực thi trong kernel-space. Điểm đáng chú ý là nếu Secure Boot được bật, kernel sẽ từ chối module này vì nó không được ký (signed) bằng private key của Debian.

(Hình 8: Kết quả dmesg hiển thị output từ kernel module)

     Trong một kịch bản tấn công thực tế, attacker nhiều khả năng sẽ tận dụng khả năng thực thi mã trong kernel-space để ẩn file, network connection và process khỏi các ứng dụng user-space tương ứng. Ví dụ, attacker có thể bổ sung mã độc nhằm loại bỏ file của ứng dụng C khỏi kết quả truy vấn filesystem khi người dùng cố gắng truy cập ứng dụng đó trong thư mục: /usr/bin hoặc ẩn TCP connection khỏi danh sách kết nối mạng khi người dùng thực thi các lệnh: netstat hoặc ss.

     Ngoài ra, kernel cũng có khả năng thực thi trực tiếp các ứng dụng user-space. Điều này đồng nghĩa attacker hoàn toàn có thể triển khai một reverse shell trực tiếp từ kernel tới remote attacker-controlled server. Tất nhiên, việc ghi lại keystroke và mở TCP connection cũng hoàn toàn có thể được thực hiện trực tiếp trong kernel-space. Khi đó, user-space keylogger — tức ứng dụng C statically compiled của chúng tôi — thậm chí có thể bị loại bỏ hoàn toàn khỏi exploit chain.

     Trong một cuộc tấn công ngoài thực tế, attacker nhiều khả năng cũng sẽ tạo một bản sao của file: /live/initrd.img sau khi tải về phiên bản initrd.img đã chỉnh sửa từ remote webserver tại một đường dẫn định trước. Kernel module sau đó sẽ cần chuyển hướng (divert) các truy cập tới /live/initrd.img sang file backup tại đường dẫn bí mật đó, đồng thời ẩn hoàn toàn quá trình tra cứu filesystem đối với file backup này. Bằng cách đó, người dùng trong user-space sẽ không thể nhận ra rằng /live/initrd.img đã bị chỉnh sửa. Ví dụ, khi người dùng chạy: sha256sum ${espmnt}/live/initrd.img, thuật toán checksum thực tế sẽ được tính trên file backup: ${espmnt}/live/initrd.img.bak (chính là đường dẫn backup mà attacker tạo ra). Kết quả là giá trị checksum vẫn khớp với giá trị hợp lệ mà người dùng mong đợi.

     Việc thu thập LUKS passphrase dưới dạng cleartext đã minh họa rõ mức độ ảnh hưởng nghiêm trọng của việc thiếu Hardware Root of Trust dưới hình thức Intel Secure Boot trong bản phân phối Tails Linux. Chỉ với một vài chỉnh sửa nhỏ, attacker hoàn toàn có thể triển khai reverse shell tới remote server, từ đó có khả năng exfiltrate toàn bộ nội dung của LUKS filesystem sau khi phân vùng này được giải mã (unlocked). Đây gần như là kịch bản tồi tệ nhất đối với một hệ điều hành vốn được thiết kế chuyên biệt cho quyền riêng tư và bảo mật.

(Hình 9: Output của custom keylogger trên remote server)

     Các sản phẩm HPE Networking giảm thiểu nguy cơ từ firmware implant, rootkit và bootkit bằng cách cung cấp một Hardware Root of Trust mạnh mẽ được bảo vệ bằng cơ chế mật mã học (cryptographically secured) ngay trong phần cứng. Điều này bao gồm: Các dòng Access Point như AP-700 Series, các gateway như 9200 Series Mobility Gateways, các dòng switch thuộc họ CX. Việc triển khai Hardware Root of Trust trên các thiết bị này đảm bảo rằng chỉ những đoạn mã được HPE Networking phát triển và xác thực mới có thể thực thi trên thiết bị. Đồng thời, các thành phần hệ thống cũng được bảo vệ khỏi việc bị chỉnh sửa trái phép bởi bên thứ ba trong suốt vòng đời sản phẩm.

(Hình 10: Video mô phỏng quá trình tấn công)

Tài liệu tham khảo

[1] https://tails.net/index.en.html[2] https://tails.net/doc/about/warnings/index.en.html[3] https://www.qemu.org/[4] https://github.com/tianocore/tianocore.github.io/wiki/OVMF[5] https://github.com/LongSoft/UEFITool[6] https://github.com/tianocore/edk2[7] https://github.com/ReFirmLabs/binwalk[8] https://buildroot.org/

CÔNG TY CỔ PHẦN DỊCH VỤ CÔNG NGHỆ DATECH

  • Địa chỉ: Số 23E4 KĐT Cầu Diễn, Tổ 7, Phú Diễn, Bắc Từ Liêm, Hà Nội

  • Điện thoại: 0243 201 2368

  • Hotline: 098 115 6699

  • Email: info@datech.vn

  • Website: https://datech.vn