2 điểm bởi GN⁺ 4 giờ trước | 1 bình luận | Chia sẻ qua WhatsApp
  • GhostLock (CVE-2026-43499) là lỗ hổng kernel được đưa vào từ Linux 2.6.39 và được vá trong 7.1, cho phép kẻ tấn công cục bộ không đặc quyền chỉ với các syscall luồng thông thường có thể gây ra stack UAF và khai thác để leo thang lên quyền root và thoát container
  • remove_waiter() trên đường dẫn proxy Requeue-PI xóa pi_blocked_on của current thay vì tác vụ đang chờ thực sự, khiến tác vụ đã quay về user space vẫn còn một con trỏ trỏ tới stack frame đã được giải phóng
  • Bằng cách tạo vòng phụ thuộc PI với ba futex và ba luồng để kích hoạt rollback -EDEADLK, rồi dựng rt_mutex_waiter giả trong bộ đệm stack có thể kiểm soát của PR_SET_MM_MAP, kẻ tấn công giành được khả năng ghi con trỏ có ràng buộc
  • Mã khai thác dùng prefetch để tìm địa chỉ cơ sở KASLR và physmap, đặt cấu trúc giả cùng stack ROP trong CPU entry area (CEA), sau đó ghi đè inet6_protos[IPPROTO_UDP] để chiếm quyền điều khiển luồng thực thi bằng gói loopback IPv6 UDP
  • Nhóm nghiên cứu đã nhận $92,337 từ Google kernelCTF với mã khai thác leo thang đặc quyền và thoát container ổn định 97%, và mọi bản phân phối Linux chưa vá đều phải nâng cấp lên bản LTS mới nhất

Phạm vi ảnh hưởng và tổng quan lỗ hổng

  • GhostLock là lỗ hổng trong kernel Linux do VEGA phát hiện, có thể bị kích hoạt bởi người dùng cục bộ không đặc quyền mà không cần đặc quyền riêng hay user namespace
  • Nó được đưa vào qua lần làm lại rtmutex trong 8161239a8bcc, và phạm vi bị ảnh hưởng là từ v2.6.39-rc1 đến v7.1-rc1
  • Lỗi được vá vào tháng 4/2026 trong 3bfdc63936dd, và cấu hình kernel cần có chỉ là CONFIG_FUTEX_PI=y
  • Kẻ tấn công có thể leo thang đặc quyền qua các bước sau
    • Giành được con trỏ kernel treo trỏ tới bộ nhớ stack của kernel chỉ bằng các syscall luồng thông thường
    • Tạo primitive bị ràng buộc có thể ghi con trỏ hoặc giá trị 0 dài 8 byte tới gần như địa chỉ tùy ý
    • Chiếm bảng hàm để kiểm soát luồng thực thi và giành quyền root
  • Mọi bản phân phối Linux chưa vá đều bị ảnh hưởng, nên cần nâng cấp lên phiên bản LTS mới nhất

Vì sao remove_waiter() dọn nhầm tác vụ

  • remove_waiter() trong kernel/locking/rtmutex.c ban đầu được viết cho đường dẫn mà luồng bị chặn tự dọn trạng thái chờ của chính nó
  • Trong slow path thông thường, current đang chạy là tác vụ sở hữu waiter, nên việc xóa current->pi_blocked_on là đúng
  • Trên đường dẫn proxy Requeue-PI, rt_mutex_start_proxy_lock() đưa rt_mutex_waiter vào hàng đợi thay cho một tác vụ khác đang ngủ, rồi rollback nếu có lỗi
    • Khi đó current là requeuer đã gọi FUTEX_CMP_REQUEUE_PI
    • Waiter thực sự là một tác vụ riêng đang ngủ trong FUTEX_WAIT_REQUEUE_PI
  • Nếu __rt_mutex_start_proxy_lock() trả về -EDEADLK, remove_waiter() sẽ gỡ waiter khỏi lock nhưng chỉ đặt current->pi_blocked_on thành NULL
  • pi_blocked_on của waiter thực sự vẫn tiếp tục trỏ tới rt_mutex_waiter nằm trên stack kernel của chính nó, và khi waiter quay về user space thì stack frame đó được xem là đã giải phóng
  • Sau đó, ngay khi quá trình dò PI chain đi qua tác vụ đó, nó sẽ dereference một đối tượng stack đã được giải phóng
  • lockdep chỉ kiểm tra liệu một pi_lock nào đó có đang được giữ hay không, chứ không kiểm tra đó là lock của ai, nên không phát hiện được lỗi này

Vòng ba futex tạo rollback -EDEADLK

  • Để đi tới đường dẫn lỗi, cần dựng một vòng phụ thuộc PI bằng ba futex và ba luồng
    • f_pi_chain: futex PI mà waiter khóa trước
    • f_pi_target: futex PI mà owner khóa trước và là đích requeue
    • f_wait: futex thường mà waiter chờ bằng FUTEX_WAIT_REQUEUE_PI
  • Trình tự kích hoạt như sau
    1. Waiter khóa f_pi_chain rồi bị chặn tại FUTEX_WAIT_REQUEUE_PI(f_wait -> f_pi_target), và rt_mutex_waiter được đặt trên stack kernel của chính nó
    2. Owner khóa f_pi_target rồi bị chặn trên f_pi_chain do waiter đang giữ
    3. Luồng main gọi FUTEX_CMP_REQUEUE_PI(f_wait -> f_pi_target)
  • Khi proxy requeue cố gắn waiter vào f_pi_target, vòng waiter → f_pi_target → owner → f_pi_chain → waiter sẽ khép kín
  • Quá trình dò PI chain trả về -EDEADLK và thực hiện rollback sai, khiến waiter thức dậy nhưng vẫn mang pi_blocked_on treo
  • Điều kiện quan trọng là requeuer phải rollback trong lúc waiter vẫn còn giữ đối tượng stack; sau khi vòng được hoàn tất thì quá trình sẽ tự diễn ra
  • Khi waiter đã quay về user space, không còn áp lực thời gian nữa và có thể kích hoạt dò chain bất cứ lúc nào sau đó bằng sched_setattr()
  • Cấu hình dùng ba luồng, nhưng bản thân race UAF vẫn có thể được kích hoạt chỉ trên một lõi CPU

Primitive ban đầu mà stack UAF cung cấp

  • Con trỏ treo trỏ tới rt_mutex_waiter từng nằm trong frame FUTEX_WAIT_REQUEUE_PI trước đó
  • Nếu đặt lại các byte có thể kiểm soát ở cùng độ sâu stack của cùng tác vụ, có thể khiến kernel dereference chúng như một rt_mutex_waiter giả
  • Tùy cách bố trí cấu trúc giả, một lần truy cập có thể mang lại hai primitive chính
    • Có thể ghi con trỏ tới gần như địa chỉ tùy ý với một số ràng buộc
    • Có thể ghi giá trị 0 dài 8 byte tới gần như địa chỉ tùy ý với một số ràng buộc
  • Trước khi ghi sẽ có nhiều lần dereference con trỏ và kiểm tra toàn vẹn, nhưng nếu thỏa điều kiện thì sau khi ghi kernel vẫn không bị crash và quay về bình thường
  • Để hoàn tất khai thác, cần đồng thời tái sử dụng stack frame, vượt qua kiểm tra cấu trúc của waiter giả, và chọn mục tiêu phù hợp với các ràng buộc ghi

Tái sử dụng stack frame đã được giải phóng bằng PR_SET_MM_MAP

  • waiter gọi prctl(PR_SET_MM, PR_SET_MM_MAP, ...) ngay sau khi quay về từ system call futex
  • prctl_set_mm_map() sao chép auxv do người dùng cung cấp vào bộ đệm stack kích thước cố định unsigned long user_auxv[AT_VECTOR_SIZE]
  • Bộ đệm này được đặt ở độ sâu stack tương tự waiter đã được giải phóng, nên một khối qword lớn, được căn chỉnh và có thể điều khiển sẽ chồng lên rt_mutex_waiter trước đó
  • Vùng chồng lấp của auxv được cấu hình như sau
    • tree: biến thành một nút rb đưa con trỏ con được chọn khi xóa là W0_BASE lên làm gốc cây
    • task: đặt thành &init_task để đi qua an toàn các dereference trong quá trình lần theo chuỗi
    • lock: chỉ định là &inet6_protos[IPPROTO_UDP] - 8 để khớp với đích ghi
    • wake_state: đặt thành 0
  • Đặt auxv trong memfd và bố trí để thao tác sao chép vượt qua ranh giới trang, sau đó một luồng anh em tạo race bằng fallocate(PUNCH_HOLE) trên trang phía sau trong lúc prctl đang chạy để kéo dài thời gian copy_from_user
  • Luồng consumer trên CPU khác gọi sched_setattr() trên waiter trong khi waiter giả vẫn còn trên stack để lần theo chuỗi PI
  • Các system call khác dùng biến cục bộ stack lớn và có thể điều khiển được như clone, setsockopt, pselect, keyctl cũng có thể đảm nhiệm vai trò tương tự
  • prctl được chọn vì bộ đệm lớn, được căn chỉnh và không cần namespace; các ứng viên bổ sung có trong mã PoC công khai

Tạo ghi con trỏ bị ràng buộc bằng xóa rb-tree

  • Ngay cả khi điều khiển được waiter giả, điều đó cũng chưa lập tức tạo ra khả năng ghi tùy ý hoàn toàn; quá trình lần theo chuỗi sẽ thực thi đường đi sau
    • Tìm waiter giả tại task->pi_blocked_on
    • Tìm rt_mutex_base giả từ fake waiter->lock
    • rt_mutex_dequeue(lock, waiter) thực hiện xóa rb-tree trong lock->waiters
  • Lợi dụng tính chất khi xóa nút gốc chỉ có một con thì nút con đó sẽ được ghi vào vị trí gốc
  • Nếu đặt lock thành target - 8, dữ liệu xung quanh sẽ được diễn giải thành các trường rt_mutex_base sau
    • target - 8: wait_lock, phải được đọc là không bị khóa
    • target: waiters.rb_root.rb_node, sẽ bị ghi đè
    • target + 8: waiters.rb_leftmost
    • target + 16: owner
  • Kết quả là thao tác ghi duy nhất được thực hiện là *(uint64_t *)target = W0_BASE
  • Địa chỉ đích xấp xỉ cần thỏa các điều kiện sau
    • 32 bit thấp của target - 0x08 phải là 0
    • Giá trị 64 bit tại target + 0x08 phải là 0
    • Giá trị của con trỏ owner tại target + 0x10, sau khi bỏ các cờ thấp, phải là 0
  • Nếu qword phía trước trông giống một spinlock đang bị khóa, trylock sẽ thất bại và kết thúc mà không ghi gì
  • Nếu các giá trị phía sau trỏ đến top waiter, owner không kiểm soát được hoặc một giá trị chưa được ánh xạ, có thể gây kernel panic
  • W0_BASE phải còn hợp lệ cho đến khi kết thúc so sánh, xếp hàng lại, cập nhật độ ưu tiên và wakeup không owner, nên sử dụng bí danh direct-map của CEA

Rò rỉ prefetch và CPU entry area

  • Tìm địa chỉ cơ sở KASLR·physmap

    • Thời gian thực thi prefetch đối với một địa chỉ cụ thể thay đổi tùy theo địa chỉ đó có được ánh xạ trong page table hiện tại hay không
    • Nếu tiến trình không đặc quyền đo thời gian trên dải địa chỉ kernel, nó có thể suy ra vị trí được ánh xạ; nguyên lý chi tiết được trình bày trong bài báo về prefetch
    • Entropy của địa chỉ cơ sở image kernel Linux mặc định chỉ khoảng 9 bit, nên có thể khôi phục địa chỉ cơ sở KASLR với độ tin cậy gần 100% bằng các phép đo lặp lại
    • Về lý thuyết, CPU có prefetch và thiếu KPTI phù hợp đều bị ảnh hưởng, nhưng trên thực tế đây chủ yếu là kỹ thuật dùng trên x86 khi KPTI bị tắt
    • Ảnh kernelCTF tắt KPTI, và ngay cả khi KPTI được bật thì vẫn có thể kết hợp prefetch với EntryBleed để khôi phục địa chỉ cơ sở image kernel qua trampoline
  • Vượt qua ngẫu nhiên hóa địa chỉ CEA

    • CPU entry area (CEA) là cấu trúc theo từng CPU trên x86, lưu stack và ngữ cảnh thanh ghi cho xử lý entry/exception
    • Khi một chương trình không đặc quyền tạo ra software exception, ngữ cảnh thanh ghi của chính nó sẽ được ghi vào pt_regs trên exception stack của CEA, tạo ra khoảng 120 byte bộ nhớ liên tiếp có thể điều khiển
    • Trước Linux 6.2, địa chỉ ảo của CEA hoàn toàn cố định nên có thể dùng trực tiếp cho cấu trúc giả, hấp thụ tác dụng phụ của dereference con trỏ và dựng stack ROP
    • Sau khi Project Zero công bố Bringing back the stack attack, từ Linux 6.2 trở đi địa chỉ ảo CEA được ngẫu nhiên hóa mạnh
    • Địa chỉ ảo CEA của mỗi CPU được ngẫu nhiên hóa khác nhau, nhưng địa chỉ vật lý là cố định, nên nếu biết địa chỉ cơ sở physmap thì có thể tính ra bí danh direct-map
    • Bằng cách kết hợp prefetch, chuẩn hóa ranh giới ứng viên và kiểm tra các trang CEA dự kiến, có thể loại trừ các bí danh lân cận và thu được cea_direct = physmap_base + CPU1_CEA_BASE
    • Trong môi trường khởi động 3.5GB của kernelCTF LTS 6.12.80, offset liên quan là 0x11c517000(+0x1f58)

Tái sử dụng CEA làm waiter giả và các đối tượng tiếp theo

  • Trước lần ghi đầu tiên, đặt waiter giả và lock tự nhất quán tại W0 của CEA
    • task được đặt thành &init_task
    • prio nhận một giá trị hợp lệ
    • wait_lock của lock được làm cho trông như đang không bị khóa
    • owner được cấu hình để đi qua an toàn các bước dequeue, xếp hàng lại, cập nhật độ ưu tiên và wakeup
  • Sau khi ghi rb-tree hoàn tất, W0 không còn cần là waiter nữa, nên có thể nạp lại CEA bằng cấu trúc mà đích đã bị ghi đè yêu cầu
  • CEA nhỏ, chỉ khoảng 120 byte, nhưng hiệu quả vì có thể đặt dữ liệu tại một địa chỉ kernel cố định có thể tính toán được
  • NPerm và kernelsnitch cũng có thể đảm nhiệm vai trò tương tự trong không gian rộng hơn
  • Exploit tuần tự hoặc đồng thời dùng một vùng CEA duy nhất làm rt_mutex_waiter giả, lock giả, inet6_protocol, các slot JOP·stack pivot và stack ROP cuối cùng

Chiếm quyền điều khiển luồng thực thi qua inet6_protos[IPPROTO_UDP]

  • Trên Linux x86_64 thông thường, sau khi lấy được địa chỉ cơ sở theo KASLR, có thể chọn một đường ngắn để ghi đè bảng hàm phù hợp hoặc đối tượng chứa bảng đó
  • Vùng quanh inet6_protos[IPPROTO_UDP] trong miền dữ liệu có thể ghi tự nhiên thỏa mãn các ràng buộc cần thiết
    • inet6_protos[16] == NULL trở thành trạng thái không bị khóa của wait_lock giả
    • inet6_protos[17] == &udpv6_protocol là mục tiêu ghi đè thực tế
    • inet6_protos[18] == NULL trở thành rb_leftmost giả
    • inet6_protos[19] == NULL trở thành owner giả
  • Khi ghi xong, inet6_protos[IPPROTO_UDP] sẽ trỏ tới inet6_protocol giả bên trong trang CEA
  • Phun CEA lần nữa để cấu hình cấu trúc như sau
    • handler: đặt thành gadget pivot đầu tiên
    • err_handler: không dùng
    • flags: đặt thành INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL
  • Sau khi connect tới ::1 rồi ghi dữ liệu, gửi một gói loopback IPv6 UDP sẽ khiến kernel gọi handler giả và cho phép kiểm soát program counter

Pivot ngắn và leo thang đặc quyền bằng DirtyMode

  • Trên mục tiêu Google kernelCTF lts-6.12.80, không tìm được gadget pivot stack đơn phù hợp, nên dùng thêm một bước load/call để đưa địa chỉ CEA vào rbp, rồi pivot bằng mov rsp, rbp; pop rbp; ret
  • Ghi đè toàn bộ kiểu ret2usr hay /proc/%P/fd/x cần khoảng 10 gadget qword, quá lớn so với không gian CEA hạn chế
  • Ở giai đoạn cuối, họ dùng DirtyMode để đổi bit quyền chỉ bằng một lần ghi, rồi thực hiện phần còn lại trong user space
  • Mục tiêu ghi là coredump_sysctls[1].mode trong dữ liệu kernel, tức chế độ truy cập của sysctl core_pattern
  • Vì nó dùng chung KASLR slide với ảnh kernel nên có thể tính ra địa chỉ, và chỉ cần một giá trị có bật bit thấp thứ hai, tức bit ghi
  • Một chuỗi ngắn pop reg; mov [reg], reg; ret sẽ đổi giá trị mode và dùng msleep để dừng an toàn luồng đã bị chiếm quyền
  • Khi /proc/sys/kernel/core_pattern trở nên có thể ghi với mọi người dùng, tiến trình không đặc quyền có thể ghi |/proc/%P/fd/666 %P và làm helper bị crash, khiến kernel chạy nhị phân của kẻ tấn công với quyền root
  • Lần ghi rb-tree ban đầu không thể chạm trực tiếp tới coredump_sysctls[1].mode do ràng buộc bố trí, nên việc đổi mode được thực hiện ở giai đoạn ROP ngắn

Toàn bộ luồng khai thác và kết quả

  • Cuộc tấn công diễn ra theo thứ tự sau
    1. Rò rỉ kernel image slide và địa chỉ cơ sở physmap bằng prefetch
    2. Dùng GhostLock để giữ lại rt_mutex_waiter dangling trong pi_blocked_on của waiter
    3. Tái sử dụng cùng khung kernel stack bằng PR_SET_MM_MAP để tạo waiter giả
    4. Dùng thao tác xóa rtmutex rb-tree để ghi con trỏ CEA vào inet6_protos[IPPROTO_UDP]
    5. Bố trí inet6_protocol giả, slot pivot và stack ROP trong CEA
    6. Gọi handler đã bị ghi đè bằng gói loopback IPv6 UDP
    7. Dùng DirtyMode để đổi bit mode của core_pattern và hoàn tất leo thang đặc quyền trong user space
  • Trong môi trường từ xa của kernelCTF, đường khai thác kết hợp CEA và DirtyMode giành được flag chỉ trong khoảng 5 giây
  • Toàn bộ exploit đã được công khai trong dự án CyberMeowfia
  • Trên Android, cách tái sử dụng stack frame và phương pháp vượt ASLR·CFI sẽ khác, và sẽ được đề cập trong một bài viết tiếp theo riêng

Các đường thay thế và biện pháp giảm thiểu

  • Không gian ROP lớn hơn

    • Bộ nhớ dựa trên NPerm có thể được dùng làm fake stack lớn sau khi chiếm quyền điều khiển luồng thực thi
    • Các đường nặng hơn như rò rỉ heap-KASLR của Lukas Maar cũng khả thi, nhưng thêm bước nên thời gian thực thi dài hơn
    • Trong kernelCTF, chuỗi ngắn nhất và đáng tin cậy nhất là có lợi, nên họ dùng tổ hợp CEA và DirtyMode
  • Bản vá kernel

    • Bản vá cuối cùng khóa pi_lock và xóa pi_blocked_on dựa trên waiter->task thay vì current
    • remove_waiter() lưu waiter_task = waiter->task rồi xử lý theo thứ tự sau
      1. Khóa waiter_task->pi_lock
      2. Xóa waiter khỏi hàng đợi rtmutex
      3. Đặt waiter_task->pi_blocked_on = NULL
      4. Trong rt_mutex_adjust_prio_chain() tiếp theo cũng truyền waiter_task thay cho current
    • Một phương án sửa riêng mà nhóm nghiên cứu gửi trước v1 được cấu hình để caller truyền rõ tác vụ sở hữu
      • Trên đường mà chính nó bị block, truyền current
      • Trong rollback proxy, truyền task mục tiêu proxy
      • Chỉ xóa khi pi_blocked_on vẫn đang trỏ tới đúng waiter đó và được bảo vệ bằng pi_lock của tác vụ
  • RANDOMIZE_KSTACK_OFFSET

    • Exploit phụ thuộc vào việc khung waiter đã giải phóng và khung user_auxv tiếp theo chồng khít một cách xác định
    • Khi bật RANDOMIZE_KSTACK_OFFSET, offset stack sẽ khác đi, biến bước này thành phỏng đoán 5 bit với xác suất khoảng 1/32
    • Trên hai mục tiêu chung đã gửi, thiết lập này mặc định tắt; còn trên mục tiêu giảm thiểu thì nó được bật nên không dùng đường exploit này
  • STATIC_USERMODE_HELPER

    • STATIC_USERMODE_HELPER chặn đường DirtyMode cụ thể này
    • Tuy vậy, vì quyền truy cập được điều khiển bằng ctl_table::mode và bảng nằm trong dữ liệu kernel có thể ghi được, có thể tổng quát hóa cùng kỹ thuật sang các thiết lập /proc/sys khác

Lịch công bố

  • 18/4/2026: Gửi lỗ hổng và bản vá nháp tới security@kernel.org
  • 20/4/2026: Lỗ hổng được sửa bằng một bản vá khác
  • 4/5/2026: Bản sửa v1 được backport
  • 30/6/2026: Google xác nhận bài nộp kernelCTF
  • 7/7/2026: Công bố phân tích kỹ thuật
  • Lỗ hổng do VEGA phát hiện tuân theo chính sách công bố tiêu chuẩn 90+30 ngày

1 bình luận

 
Ý kiến trên Hacker News
  • Đã thử trên 3 thiết bị dùng Android 9·13·16 với các phiên bản Firefox khác nhau dưới 150; 2 máy rơi vào vòng lặp khởi động và phải vào chế độ khôi phục, còn 1 máy thì tắt nguồn. Bản demo đổi hình nền trên các thiết bị Pixel được hỗ trợ, và có thể xem trang thử nghiệm tại IonStack
    Khi xem blog hay các trang tùy ý trên thiết bị cá nhân, an toàn hơn là cài riêng một trình duyệt dòng Chromium như Chromite ngoài trình duyệt chính, tắt JavaScript và bộ giải mã video tăng tốc phần cứng thường bị tấn công trong phần cờ, rồi dùng chế độ đọc cho các trang bị lỗi. Hoặc cũng có thể để riêng một máy tính bảng chuyên dụng

    • Hiện mới chỉ thử trên Pixel 10, nhưng đã có vài PR muốn hỗ trợ thêm thiết bị khác; có thể xem tại https://github.com/NebuSec/CyberMeowfia
    • Khi chuyển kernel exploit sang thiết bị khác, thấy nó rất nhạy với cách trình biên dịch bố trí stack frame ở từng bản build kernel. Sau khi tìm được kiểu stamp và offset phù hợp với một bản build cụ thể thì nó chạy khá ổn định
    • Tôi đã chấp nhận rủi ro chạy thử trên Samsung S26 Ultra, và sẽ công bố đầy đủ kết quả sau khi cài adb để kiểm tra
      Vừa truy cập trang thử nghiệm thì tab Firefox hiện đầu ra, có vẻ mã proof-of-concept đã chạy, nhưng sau đó điện thoại bị treo và từ chối mọi thao tác nhập. Chỉ có khởi động lại là hoạt động; tôi thắc mắc trong tình huống kernel dường như đã treo thì vì sao máy vẫn phản hồi với sự kiện khởi động lại. Màn hình vẫn bật, hiển thị một phần kết quả chạy cho đến khi trình bảo vệ màn hình kích hoạt
    • Sẽ thật ấn tượng nếu có thể dùng nó để root các thiết bị Android vẫn chưa root được; tôi muốn biết có cách nào khả thi không
    • Lỗ hổng Firefox có vẻ là nhầm lẫn kiểu trong trình biên dịch JIT IonMonkey, CVE-2026-10702: https://www.sentinelone.com/vulnerability-database/cve-2026-10702/
  • Xin gửi lời khen lớn tới các nhà nghiên cứu bảo mật vì không chỉ tìm ra exploit mà còn không công bố script leo thang đặc quyền cục bộ zero-day để ai cũng dùng được ngay như copyfail
    Tôi đã thử leo thang đặc quyền cục bộ (LPE) trên Rocky Linux 9 trong vài giờ nhưng may mắn là chưa thành công. Nếu không có nhiều thời gian rảnh hoặc kỹ năng cực cao thì có vẻ khó biến nó thành tấn công thực tế trên các bản phân phối doanh nghiệp

  • Tôi tự hỏi liệu trên những điện thoại thông thường không thể mở khóa bootloader, lỗ hổng này có thể dùng để mở khóa bootloader hay không. Nếu được thì đây có thể là một trong những sự kiện lớn nhất từng xảy ra với hệ sinh thái Android

  • Có lẽ nên đưa LPE vào tiêu đề để đa số mọi người yên tâm quay lại cuối tuần của mình

    • Không hẳn là chuyện có thể yên tâm. Thông thường exploit đặc quyền cục bộ nghĩa là leo từ quyền người dùng thường lên quyền root, mà ứng dụng quyền thường vốn cũng đã có thể gây hại lớn nên người ta thường không quá lo
      Nhưng đợt này có thể kích hoạt ngay cả bên trong tiến trình bị sandbox rất chặt, như tiến trình trình duyệt cô lập của Firefox. Kẻ tấn công chỉ cần nối một lỗ hổng JavaScript để thực thi mã cục bộ trong sandbox cô lập với lỗ hổng lần này để leo lên kernel mode, nên phải cập nhật cả Firefox lẫn Linux kernel
    • Cuộc tấn công ở bình luận phía trên trông như thể lấy quyền root trực tiếp từ JavaScript, nhưng thực ra nó xâu chuỗi hai exploit khác nhau
    • Nếu có thể thoát container thì chẳng phải vẫn sẽ ảnh hưởng đến rất nhiều người sao
    • Vì họ cũng tìm ra lỗ hổng nhầm lẫn kiểu của Firefox/IonMonkey, chỉ cần truy cập một website bất kỳ là thiết bị có thể bị chiếm quyền rất nhanh
    • Dạo này có cảm giác người ta đang tích sẵn hàng trăm zero-day chỉ để tiêu hao trong những tình huống như thế này. Từ SSH đến Node.js, cứ vài tuần lại có vấn đề mới, nên trừ khi đặt toàn bộ liên lạc sau WireGuard, còn không thì gần như phải xem tất cả như lỗ hổng từ xa
  • Tôi bắt đầu chú ý ngay từ đoạn “Google đã trả 92.337 USD tiền thưởng kernelCTF”

    • Xét phạm vi ảnh hưởng thì có vẻ là số tiền nhỏ. Không biết có phải các công ty chỉ trả nhiều tiền cho exploit từ xa hay không
  • Không rõ điều này có nghĩa là ứng dụng Android có thể chạy mã native bằng NDK để lấy quyền root hay không, và SELinux có giúp phòng thủ được không

    • Các điện thoại không phải flagship hiếm khi nhận cập nhật, nhất là cập nhật kernel, nên khả năng thực tế là có vẻ khá cao
      Dù vẫn có thể backport bản vá sang kernel cũ, nhưng changelog cập nhật smartphone hiếm khi nêu rõ CVE, nên công cụ kiểm tra lỗ hổng gần như là cách xác nhận duy nhất. Nếu một ứng dụng từ Play Store hoặc nguồn ngoài bị xâm phạm thì nó có thể lấy quyền root ngay, vì vậy nguyên tắc kiểm tra mức độ tin cậy và việc kiểm toán khi cài đặt vẫn rất quan trọng
      Trong tương lai, có thể việc kiểm tra này sẽ được thêm vào mọi mức Google Play Integrity, khiến nhiều ứng dụng không thể cài trên điện thoại chưa vá. Với trình duyệt, nơi khó tránh các trang tùy ý và quảng cáo, việc thoát sandbox còn vượt qua cả cô lập ứng dụng nên nghiêm trọng hơn, khá giống JailbreakMe trên iOS
    • Nếu chính kernel đã bị xâm phạm thì SELinux không thể phòng thủ. Sandbox Android hay công nghệ container như Docker cũng không chặn được exploit này; biện pháp cô lập thực tế duy nhất là ảo hóa hoàn toàn. Nếu dùng KVM thì phải giả định rằng bản vá CVE-2026-53359 công bố tuần trước đã được triển khai ở mọi nơi
      Với Linux phát hành trong 15 năm qua, bất kỳ ứng dụng nào có thể chạy mã native đều có thể giành quyền root trên thiết bị cho đến khi bản cập nhật kernel đến nơi
  • Việc GhostLock được đưa vào từ Linux 2.6.39 và chỉ đến Linux 7.1 mới được sửa thật sự gây sốc

  • Tôi thấy như đã đọc các bình luận này từ hôm trước rồi, nhưng thời gian đăng đều hiện trong vòng 10 giờ; không biết có phải phần hiển thị thời gian của HN bị lỗi không

    • Khả năng cao là do hệ thống re-up của HN. Khi bài này được đẩy lên lại, dấu thời gian của các bình luận cũ đã được tính lại theo thời gian tương đối; có thể xem nội dung liên quan tại https://hn.algolia.com/?dateRange=all&page=0&prefix=true&query=by%3Adang%20timestamps%20re-up&sort=byDate&type=comment
      Trong danh sách “underwater” mà tôi xem hằng ngày — tức những bài được upvote nhiều nhưng vì lý do nào đó không lên được trang đầu — bài này đứng đầu nên đã được cho hiển thị lại. Trông có vẻ kỳ lạ, nhưng hiện vẫn chưa có phương án nào đỡ gây rối hơn
    • Đôi khi các bài tương tự được gộp lại thành một và cả bình luận cũng được hợp nhất