Giành quyền thực thi mã kernel trên Pixel 8 đã bật MTE
(github.blog)- CVE-2023-6241 là một lỗi logic trong đơn vị quản lý bộ nhớ của GPU Arm Mali, cho phép ứng dụng Android độc hại đạt tới thực thi mã kernel tùy ý và giành quyền root ngay cả trên Pixel 8 đã bật kernel MTE
- Đối tượng bị ảnh hưởng là các thiết bị GPU Arm Mali đời mới dùng Command Stream Frontend(CSF), bao gồm Google Pixel 7 và Pixel 8
- Lỗ hổng hoạt động bằng cách lợi dụng một khoảng thời gian ngắn khi khóa được nhả trong quá trình mở rộng bộ nhớ JIT để tạo ra sự không nhất quán giữa ánh xạ GPU và mảng backing page
- Khai thác tận dụng ánh xạ GPU còn sót lại tới backing page đã được giải phóng, khiến trang đó được tái sử dụng làm PGD của ngữ cảnh GPU, rồi ánh xạ bộ nhớ kernel và mã kernel
- MTE bắt lỗi không khớp giữa con trỏ và thẻ bộ nhớ, nhưng luồng tấn công này diễn ra khi GPU truy cập trực tiếp địa chỉ vật lý, nằm ngoài phạm vi bảo vệ của MTE
Phạm vi lỗ hổng và trạng thái bản vá
- CVE-2023-6241 là lỗ hổng GPU Arm Mali, cho phép ứng dụng Android độc hại thực thi mã kernel tùy ý và giành quyền root trên thiết bị
- Lỗ hổng được báo cáo cho Arm vào ngày 15/11/2023 và được sửa trong Arm Mali driver r47p0 công bố ngày 14/12/2023
- Bản sửa cho Android được đưa vào bản cập nhật bảo mật tháng 3/2024
- Đối tượng bị ảnh hưởng là các thiết bị GPU Arm Mali đời mới sử dụng tính năng CSF(Command Stream Frontend); Google Pixel 7 và Pixel 8 được nêu làm ví dụ
- Khai thác đã được xác nhận hoạt động trên Pixel 8 ngay cả khi kernel MTE được bật
Mô hình phòng vệ của Arm64 MTE
- MTE(Memory Tagging Extension) là tính năng phần cứng trên các bộ xử lý Arm mới, so sánh thẻ của con trỏ và khối bộ nhớ để phát hiện lỗi hỏng bộ nhớ
- Con trỏ Arm64 là 64-bit, nhưng không gian địa chỉ ứng dụng thực tế thường không quá 52-bit, nên có thể dùng một phần các bit cao để lưu thẻ
- Với tràn tuyến tính, thẻ của khối bộ nhớ liền kề có thể khác với thẻ con trỏ; với use-after-free, việc thay đổi thẻ trong quá trình giải phóng và cấp phát lại có thể tạo ra không khớp
- Khác với các biện pháp giảm thiểu giai đoạn sau như kCFI, MTE là biện pháp giảm thiểu giai đoạn đầu nhằm bắt lỗi ngay tại thời điểm hỏng bộ nhớ mới xảy ra
- Do số bit thẻ bị giới hạn nên không thể tránh va chạm; chỉ cần dùng thẻ 4-bit cũng làm xác suất thành công ngẫu nhiên giảm xuống 1/16
- Nếu rò rỉ được giá trị con trỏ và khối bộ nhớ bằng tấn công kênh kề như Spectre, có thể khớp đúng thẻ để vượt qua MTE, nhưng kiểu rò rỉ này chủ yếu khả thi với kẻ tấn công cục bộ
- Hiện chỉ Google Pixel 8 cho phép bật MTE trong tùy chọn nhà phát triển, và MTE mặc định bị tắt
- Cần thêm quy trình để bật MTE trong kernel
Cuộc đua trong bộ nhớ JIT của Mali
- Ứng dụng người dùng dùng driver Mali GPU mở tệp driver và tạo, khởi tạo đối tượng kernel
kbase_contextbằng các lời gọiioctl kbase_contextquản lý nhiều loại bộ nhớ được chia sẻ giữa thiết bị GPU và ứng dụng không gian người dùng- Vùng bộ nhớ của Mali GPU được biểu diễn bằng
kbase_va_region;nr_pagesbiểu thị kích thước ảo, còngpu_alloc->nentsbiểu thị số backing page thực tế - Bộ nhớ JIT là native memory do kernel driver quản lý vòng đời, và ứng dụng cấp phát hoặc giải phóng bộ nhớ JIT bằng lệnh GPU
- Trên GPU CSF, lệnh phần mềm và lệnh phần cứng nằm trong các hàng đợi khác nhau
- Có thể tạo
kbase_kcpu_command_queuebằngKBASE_IOCTL_KCPU_QUEUE_CREATE - Đưa lệnh vào hàng đợi bằng
KBASE_IOCTL_KCPU_QUEUE_ENQUEUE BASE_KCPU_COMMAND_TYPE_JIT_ALLOCvàBASE_KCPU_COMMAND_TYPE_JIT_FREEđược dùng để cấp phát/giải phóng JIT
- Có thể tạo
kbase_jit_allocatetìm vùng có thể tái sử dụng trong pool bộ nhớ JIT đã giải phóng, và nếu kích thước vật lý không đủ thì tăng backing page bằngkbase_jit_growkbase_jit_growcó thể tạm thời nhảkctx->reg_lockvàkctx->mem_partials_locktrong lúc gọikbase_mem_pool_growkctx->reg_lockbảo vệ truy cập đồng thời tới vùng bộ nhớ, vì vậy khoảng thời gian khóa bị nhả trở thành cửa sổ race
Luồng kích hoạt CVE-2023-6241
- Khi GPU truy cập địa chỉ vùng bộ nhớ không được backing bởi trang vật lý, lỗi truy cập bộ nhớ GPU sẽ xảy ra
kbase_mmu_page_fault_workercó thể kiểm tra vùng có thể mở rộng hay không, rồi cấp phát và ánh xạ ngay các backing page cần thiết- Khi được tạo, vùng JIT thỏa điều kiện GROWABLE_FLAGS_REQUIRED, bao gồm
KBASE_REG_PF_GROWvàKBASE_REG_GPU_WR - Cờ
KBASE_REG_DONT_NEED, được gắn khi vùng JIT bị giải phóng, bị loại bỏ trongkbase_mem_evictable_unmakeở đầukbase_jit_grow - Kết quả là nếu tạo lỗi trang GPU trên cùng vùng JIT trong cửa sổ race khi
kbase_mem_pool_growđang chạy, trình xử lý lỗi có thể mở rộng vùng đó - Nếu trình xử lý lỗi thay đổi
reg->gpu_alloc->nents, các giá trịold_sizevàdeltamàkbase_jit_growđã lưu trước đó sẽ lệch khỏi trạng thái thực tế - Sau đó
kbase_alloc_phy_pages_helper_lockedvàkbase_mem_grow_gpu_mappingthực hiện cấp phát backing page và ánh xạ GPU bằng các giá trị stale, tạo ra sự không nhất quán giữa ánh xạ GPU và mảngpages - Race này dễ thắng vì
kbase_mem_pool_growbao gồm một lần cấp phát bộ nhớ lớn
Cách tấn công thay đổi sau bản vá GHSL-2023-005
- Trong lỗ hổng trước đó GHSL-2023-005, một luồng khác có thể dùng
KBASE_IOCTL_MEM_COMMITđể thu nhỏ vùng JIT, làm vô hiệuold_sizevàdelta - Sau bản vá GHSL-2023-005, không còn có thể thay đổi kích thước bộ nhớ JIT bằng
KBASE_IOCTL_MEM_COMMIT ioctl - Với CVE-2023-6241, trong cửa sổ race không thể thu nhỏ vùng mà chỉ có thể mở rộng
- Nếu chỉ mở rộng đơn thuần, một số backing page cuối cùng chỉ là không được ánh xạ vào GPU, còn dạng ánh xạ liên tục từ đầu vẫn được giữ nên chưa gây vấn đề ngay
- Khai thác tạo ánh xạ mới phía sau unmapped gap bằng lỗi GPU bổ sung, rồi thông qua việc giải phóng JIT sau đó để đặt điểm shrink vào bên trong gap, tạo trạng thái có thể bị lợi dụng
Giả định dễ tổn thương khi gỡ ánh xạ GPU
kbase_mmu_teardown_pgd_pagesduyệt bảng trang GPU và đánh dấu các entry là invalid để loại bỏ ánh xạ địa chỉ GPU- Hàm này giả định rằng nếu PTE cấp cao là invalid thì toàn bộ dải địa chỉ lớn mà entry đó bao phủ đã được unmapped, nên bỏ qua
- Một PTE cấp 2 bao phủ phạm vi 512 trang
- Trong
kbase_va_regionbình thường, các địa chỉ ảo đã ánh xạ luôn liên tục từ đầu vùng và không có gap ở giữa, nên hành vi bỏ qua này là an toàn - Khai thác CVE-2023-6241 tạo một unmapped gap giữa các ánh xạ, rồi đặt điểm bắt đầu shrink vào trong gap
kbase_mmu_teardown_pgd_pagesgặp PTE cấp 2 invalid và bỏ qua 512 trang, nhưng một phần địa chỉ phía sau thực tế vẫn có thể đang được ánh xạ- Địa chỉ GPU bị bỏ qua sai vẫn giữ quyền truy cập tới trang vật lý đó ngay cả sau khi backing page đã được giải phóng
Quá trình dẫn tới thực thi mã kernel
- Khi giải phóng vùng JIT, backing page được trả lại, nhưng ánh xạ GPU còn sót lại do lỗi vẫn có thể tiếp tục truy cập các trang đã giải phóng
- Backing page đã giải phóng sau đó có thể được tái sử dụng làm trang kernel khác
- Một trong các kỹ thuật được dùng là khiến backing page đã giải phóng được tái sử dụng làm PGD(page table global directory) của GPU
kbase_context - Việc cấp phát backing page của driver Mali được thực hiện theo phân cấp
- Trước tiên lấy trang từ
kbase_mem_poolcủakbase_contexthiện tại - Nếu không đủ thì dùng
pool->next_pool - Nếu vẫn không đủ thì cấp phát trực tiếp qua kernel buddy allocator
- Trước tiên lấy trang từ
pool->next_poollà pool bộ nhớ do driver Mali quản lý và được chia sẻ bởi mọikbase_context, đồng thời cũng được dùng để cấp phát PGD của ngữ cảnh GPU- Nếu trang đã giải phóng được tái sử dụng làm PGD, địa chỉ GPU còn sót lại có thể được dùng để ghi lại PGD đó từ GPU
- Ghi lại PGD cho phép ánh xạ bộ nhớ kernel và mã kernel tùy ý vào GPU
- Ở trạng thái này, có thể ghi lại mã kernel để thực thi mã kernel tùy ý, cũng như đọc/ghi dữ liệu kernel để thay đổi credential của tiến trình và vô hiệu hóa SELinux
- Khai thác và ghi chú cấu hình cho Pixel 8 được công bố tại kho lưu trữ GitHub Security Lab
Vì sao có thể vượt qua MTE
- Luồng khai thác này không cần bước vượt qua MTE chuyên biệt nào
- MTE là tính năng kiểm tra xem thẻ của khối bộ nhớ mà con trỏ trỏ tới có khớp hay không, nhằm bắt lỗi dereference sai
- Tại thời điểm kích hoạt CVE-2023-6241, xảy ra sự không nhất quán giữa mảng
pagesvà ánh xạ GPU, nhưng nếu xét riêng từng phần thì không có entry invalid - Khi
kbase_mmu_teardown_pgd_pagesbỏ qua việc loại bỏ ánh xạ GPU, địa chỉ vật lý của trang bộ nhớ đã giải phóng vẫn còn trong bảng trang GPU - Khi GPU truy cập trang đã giải phóng này, nó truy cập trực tiếp địa chỉ vật lý nên không đi qua kiểm tra dereference con trỏ
- Ảnh hưởng của MTE đối với truy cập bộ nhớ GPU cũng chưa chắc chắn
- Kết quả là lỗi này vượt qua bảo vệ MTE bằng cách lợi dụng đường truy cập trực tiếp vào bộ nhớ vật lý của GPU, một bộ đồng xử lý
Bề mặt tấn công vẫn còn sau MTE
- CVE-2023-6241 cho thấy ngay cả trên Pixel 8 đã bật kernel MTE, một lỗi đơn lẻ vẫn có thể dẫn tới thực thi mã kernel tùy ý
- MTE là một bước tiến quan trọng trong giảm thiểu lỗi hỏng bộ nhớ và có thể khiến nhiều lỗ hổng hỏng bộ nhớ không thể khai thác, nhưng không phải lá chắn vạn năng
- Trong trường hợp này, GPU vượt qua MTE bằng cách truy cập trực tiếp bộ nhớ vật lý
- Khi các biện pháp giảm thiểu bằng phần cứng và phần mềm ở phía CPU ngày càng nhiều, các bộ đồng xử lý và driver kernel của chúng vẫn có thể tiếp tục là bề mặt tấn công mạnh
1 bình luận
Các ý kiến trên Hacker News
Điểm mấu chốt ở đây là GPU từ lâu đã là vấn đề đau đầu của Android
GPU có quyền truy cập rất mạnh vào AP, nên trên thực tế có thể vượt qua các biện pháp giảm thiểu đã dựng lên phía trước. Lỗi trong mã ánh xạ của driver dẫn đến các primitive tấn công mạnh, và đã nhiều lần bị lạm dụng trong các exploit ngoài đời thực. Rốt cuộc, có vẻ khó có thay đổi lớn cho đến khi kiến trúc được thiết kế lại
Điểm thú vị của lỗ hổng này là nó là một lỗi logic trong bộ quản lý bộ nhớ của GPU Arm Mali, và có thể vượt qua Memory Tagging Extension
Tuy nhiên phần còn lại của bài viết có vẻ giải thích rằng nguyên nhân thực sự là race condition, còn use-after-free là hệ quả của nó
Các bản cài đặt GrapheneOS trước bản cập nhật tháng 3 có bị ảnh hưởng không?
Đôi khi họ áp dụng mức bản vá bảo mật AOSP trước khi phát hành, hoặc backport cả các bản sửa bảo mật từ AOSP hay mã nguồn kernel chưa được công khai
Sửa: có thể bỏ qua. Tôi đã nhầm với bài viết gần đây trên blog GrapheneOS nói rằng “đã tìm thấy vấn đề khiến MTE cũng được áp dụng cho tất cả ứng dụng hệ thống”. GrapheneOS đã đưa vào “toàn bộ mức bản vá bảo mật 2024-03-05” trong bản phát hành 2024030600, nên có vẻ bản vá này cũng đã được bao gồm
Tính an toàn bộ nhớ theo xác suất của Arm MTE là bước đệm để tiến tới phần cứng CHERI mang tính quyết định, https://saaramar.github.io/memory_safety_blogpost_2022/ và https://news.ycombinator.com/item?id=39668053
Biện pháp giảm thiểu đúng phải nhắm vào primitive tấn công cấp một, tức nguyên nhân gốc của lỗi. Về giải pháp phần cứng có CHERI(Morello, CheriIoT), MTE; về biện pháp giảm thiểu bằng phần mềm có kalloc_type+dataPAC, AUTOSLAB, Firebloom, GuardedMemcpy, CastGuard, giảm bề mặt tấn công; còn về ngôn ngữ lập trình an toàn có Rust và Swift. MTE và CHERI phối hợp tốt với nhau, giúp loại bỏ các lỗi trong lĩnh vực này ngay từ nguyên nhân gốc. MSR, MSRC, Azure Silicon đã thúc đẩy hướng thu nhỏ CHERI xuống tới đặc tả lõi RISC-V nhỏ nhất là RISC-V32E
Microsoft Research đã công bố mã nguồn mở stack phần cứng/phần mềm CHERI cho thiết bị IoT, https://msrc.microsoft.com/blog/2023/02/first-steps-in-cheri...
Vi điều khiển dựa trên CHERI nhằm đạt được các bảo đảm bảo mật rất mạnh bằng cách cùng thiết kế kiến trúc tập lệnh (ISA), giao diện nhị phân ứng dụng (ABI), mô hình cách ly và phần lõi của stack phần mềm. Vi điều khiển này đạt được giảm thiểu mang tính quyết định về an toàn không gian thông qua các tính năng CHERI-ISA, giảm thiểu mang tính quyết định về an toàn thời gian của heap và stack giữa các compartment thông qua load barrier, zeroing, revocation và kiểm soát luồng thông tin 1 bit, cùng compartmentalization chi tiết thông qua các tính năng CHERI-ISA bổ sung và một monitor nhỏ
David Chisnall, U of Cambridge, https://lobste.rs/s/gnjx2n/c_can_be_memory_safe#c_9ohzku qua https://eclypsium.com/blog/a-faster-path-to-memory-safety-ch...
“Có khoảng 13 tỷ dòng mã C/C++ nguồn mở nằm trong nhiều trusted computing base, và nếu tính cả mã độc quyền thì con số còn lớn hơn. Ngay cả nếu từ bây giờ mọi người đều ngừng viết C/C++ và mọi kỹ sư phần mềm đều tập trung viết lại mã legacy bằng ngôn ngữ an toàn, thì cũng sẽ mất 5–10 năm để thay thế tất cả; và khi thay mã đã được kiểm chứng lâu năm bằng mã mới cần các thuật toán và cấu trúc dữ liệu khác phù hợp với các idiom được phép của ngôn ngữ an toàn, rất có khả năng sẽ phát sinh nhiều lỗi logic.”
“Nếu không viết lại mà chỉ ngừng viết mã C/C++, với tốc độ thay thế mã thông thường, sẽ mất khoảng 50 năm để trusted computing base trở nên hoàn toàn an toàn. Nếu mọi người không đồng thuận ngừng C/C++, thì ít nhất là 100 năm.”
“Ngược lại, nếu các nhà sản xuất CPU lớn tung ra CPU CHERI trong vòng 5 năm, thì trong vòng 15 năm kể từ hôm nay, phần lớn máy, đặc biệt là các máy có giá trị cao, sẽ có an toàn bộ nhớ mà không cần lập trình viên thay đổi hành vi.”
Cái đầu tiên là hệ thống Sonata: https://github.com/lowRISC/sonata-system. Nó gồm một PCB chuyên dụng có FPGA cùng nhiều thiết bị ngoại vi và header. Thiết kế PCB đã hoàn tất và dự kiến có thể mua qua Mouser; ngay cả layout bo mạch cũng là mã nguồn mở nên nếu muốn bạn có thể tự lắp ráp. Hiện họ đang làm RTL cho FPGA. Khi hoàn tất, bạn sẽ có một hệ thống kiểu vi điều khiển dựa trên CHERIoT, kèm tài liệu và công cụ
Ngoài ra họ cũng đang tạo hệ thống Symphony kết hợp Sonata với root of trust OpenTitan Earl Grey: https://github.com/lowRISC/symphony-system
Hơn nữa lần cuối tôi xem thì CHERI không sound. Vẫn có thể viết lỗi bộ nhớ trên đó; chuyện đó đã được sửa chưa?
Chỉ riêng tranh luận kiểu nhà để xe đạp có lẽ cũng mất chừng đó thời gian
Có vẻ exploit này có thể được viết bằng hầu hết các ngôn ngữ, kể cả Rust
Phần cứng tệ đến mức đó sao? Trời ơi...
Cách này khả thi vì GPU không cho phép truy cập phần cứng tương đối trực tiếp như CPU
Đây là một nghiên cứu và bài viết xuất sắc, nhưng việc nó xuất hiện trên blog GitHub thì hơi bất ngờ mà cũng đáng mừng
Có ai biết “lý do kinh doanh” của GitHub khi thực hiện kiểu nghiên cứu này là gì không? Không phải ý nói nhất thiết phải có lý do kinh doanh, nhưng thấy nó ở đây thì hơi ngạc nhiên
Năng lực nghiên cứu đó đã tiếp nối thành GitHub Security Lab. Semmle đã tạo ra CodeQL, và hiện được GitHub cung cấp (https://docs.github.com/en/code-security/code-scanning/intro...). GitHub và Microsoft muốn gắn CodeQL với “những hiểu biết bảo mật sâu sắc” (https://www.microsoft.com/en-us/security/blog/2023/11/02/ann...)
Vì vậy họ tiếp tục tài trợ cho những nghiên cứu bảo mật mới mẻ như thế này, và các chuyên gia bảo mật trong ngành rất biết ơn điều đó
GitHub cũng có ứng dụng, và bảo mật của ứng dụng đó không nằm ngoài phạm vi của GitHub. Nếu kẻ tấn công có thể cài một ứng dụng ẩn trên điện thoại, chúng có thể làm nhiều việc như thể là người dùng. Nếu đó là người có ảnh hưởng trên GitHub thì thiệt hại có thể khá lớn, nên việc tìm các lỗ hổng kiểu này cũng có lợi cho GitHub
Vì vậy họ có thể quan tâm đến việc kiểm tra và xác minh các tính năng bảo mật của phần cứng Arm để sandboxing bằng MTE
Nếu xét trực tiếp thì sản phẩm GitHub không nhất thiết cần chuyên gia bảo mật Android. Nhưng về dài hạn thì có lợi ích tiềm năng
[0]: https://en.wikipedia.org/wiki/Basic_research
Thật ngạc nhiên là vẫn chưa có trường hợp nào làm CPU và điện thoại gần như không có GPU, hoặc không có GPU, rồi gọi đó là điện thoại doanh nhân
Xét về bảo mật, chi phí và mức tiêu thụ điện thì lợi ích có vẻ rất rõ ràng