1 điểm bởi GN⁺ 2024-07-02 | 1 bình luận | Chia sẻ qua WhatsApp
  • Do điều kiện tranh chấp trong signal handler của máy chủ OpenSSH sshd, một client chưa xác thực có thể gây thực thi mã từ xa trên máy chủ cấu hình mặc định nếu không xác thực trong thời hạn trước xác thực LoginGraceTime
  • Lỗ hổng này là một hồi quy (regression) của CVE-2006-5051 năm 2006; nó xuất hiện trở lại từ OpenSSH 8.5p1 đến trước 9.8p1 sau khi commit OpenSSH 8.5p1 vào tháng 10/2020 gỡ bỏ cơ chế bảo vệ trong sigdie()
  • Trên Linux dùng glibc, syslog() gọi các hàm không an toàn trong ngữ cảnh tín hiệu bất đồng bộ (async-signal-unsafe) như malloc()free(), có thể dẫn đến RCE root không cần xác thực trong phần mã privileged của sshd không bị sandbox
  • Thử nghiệm được thực hiện trên máy ảo i386 và mạng ổn định với packet jitter khoảng 10ms; trên Debian 12.5.0 OpenSSH 9.2p1, cần trung bình khoảng 10.000 lần thử và mất khoảng 6–8 giờ để có root shell với điều kiện MaxStartups=100, LoginGraceTime=120
  • OpenSSH đã sửa bằng commit 81c1099 ngày 6/6/2024; nếu khó cập nhật hoặc biên dịch lại, đặt LoginGraceTime 0 có thể chặn RCE nhưng vẫn còn rủi ro DoS do cạn kiệt kết nối MaxStartups

Vị trí phát sinh lỗ hổng

  • Vấn đề của OpenSSH sshd bắt đầu từ SIGALRM handler hoạt động trước xác thực
    • Nếu client không xác thực trong LoginGraceTime, SIGALRM handler sẽ được gọi bất đồng bộ
    • Handler này gọi các hàm không async-signal-safe như syslog()
    • Giá trị mặc định là LoginGraceTime=120 giây; trong các phiên bản OpenSSH cũ là 600 giây
  • Lỗ hổng này là một hồi quy của CVE-2006-5051
    • CVE-2006-5051 là điều kiện tranh chấp trong signal handler ở OpenSSH trước 4.4, được Mark Dowd báo cáo năm 2006
    • Vào tháng 10/2020, commit 752250c của OpenSSH 8.5p1 đã vô tình xóa #ifdef DO_LOG_SAFE_IN_SIGHAND khỏi sigdie()
  • Phạm vi ảnh hưởng theo phiên bản được phân tách rõ ràng
    • OpenSSH trước 4.4p1: dễ bị tấn công nếu chưa backport các bản vá liên quan đến CVE-2006-5051 hoặc CVE-2008-4109
    • OpenSSH từ 4.4p1 đến trước 8.5p1: không dễ bị điều kiện tranh chấp này vì sigdie() đã được đổi sang lời gọi _exit(1) an toàn
    • OpenSSH từ 8.5p1 đến trước 9.8p1: dễ bị tấn công trở lại do cơ chế bảo vệ bị gỡ bỏ

Môi trường bị ảnh hưởng và ngoại lệ

  • Mục tiêu khai thác từ xa là Linux dùng glibc
    • syslog() của glibc gọi nội bộ các hàm async-signal-unsafe như malloc()free()
    • Mã dễ bị tấn công nằm trong phần mã privileged của sshd, chạy với đầy đủ đặc quyền và không bị sandbox
    • Kết quả là có thể thực thi mã root từ xa không cần xác thực
  • Các libc hoặc hệ điều hành khác không nằm trong phạm vi khảo sát
  • OpenBSD không bị ảnh hưởng
    • SIGALRM handler của OpenBSD gọi syslog_r() thay vì syslog()
    • syslog_r() là phiên bản async-signal-safer do OpenBSD tạo ra năm 2001

Tiền đề của nghiên cứu khai thác từ xa

  • Để khai thác điều kiện tranh chấp này từ xa, cần giải quyết ba vấn đề
    • Cần một code path khiến sshd rơi vào trạng thái không nhất quán khi SIGALRM chen vào đúng thời điểm
    • Cần đi tới code path đó và tăng xác suất bị ngắt đúng thời điểm
    • Cần canh được timing đó ngay cả trong môi trường mạng từ xa
  • Nghiên cứu bắt đầu từ môi trường i386 của OpenSSH cũ thay vì đối đầu ngay với các cơ chế bảo vệ hiện đại, rồi mở rộng sang các phiên bản gần đây
  • Điều kiện thử nghiệm có các giới hạn rõ ràng
    • Chỉ nhắm tới máy ảo, không phải máy chủ bare-metal
    • Mạng là đường truyền tương đối ổn định với packet jitter khoảng 10ms
    • Nhiều phần của exploit vẫn có thể được cải thiện thêm
    • Công việc exploit trên amd64 đã bắt đầu, nhưng khó hơn nhiều do ASLR mạnh hơn

Thử nghiệm với các mục tiêu OpenSSH cũ

  • Debian 3.0r6, OpenSSH 3.4p1

    • Mục tiêu là SSH-2.0-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3, môi trường năm 2005 của Debian 3.0r6
    • Phiên bản Debian này là phiên bản Debian đầu tiên bật privilege separation theo mặc định, và các bản vá lỗ hổng chính thời đó đã được áp dụng
    • Khai thác sử dụng việc ngắt free()trạng thái heap không nhất quán
      • Ngắt lời gọi free() trong mã phân tích khóa công khai bằng SIGALRM
      • Sau đó tận dụng trạng thái heap không nhất quán ở một free() khác trong packet_close()
    • glibc 2.2.5 chưa có cơ chế gia cố chống kỹ thuật unlink() của Solar Designer
    • Tấn công ghi đè __free_hook để chuyển luồng thực thi tới địa chỉ shellcode trên heap
    • Phiên bản Debian này không có ASLR lẫn NX
    • Sau khi cải thiện timing, cần trung bình khoảng 10.000 lần thử
    • Với MaxStartups=10, LoginGraceTime=600, mất trung bình khoảng 1 tuần để có root shell từ xa
  • Ubuntu 6.06.1, OpenSSH 4.2p1

    • Mục tiêu là SSH-2.0-OpenSSH_4.2p1 Debian-7ubuntu3, môi trường năm 2006 của Ubuntu 6.06.1
    • Đây là phiên bản Ubuntu cuối cùng vẫn dễ bị CVE-2006-5051
    • Vì glibc 2.3.6 lấy mandatory lock khi vào các hàm họ malloc, cách khai thác bằng việc ngắt malloc rồi gọi một malloc khác sẽ dẫn đến deadlock
    • Code path khai thác cuối cùng dùng PAM
      • pam_start() thiết lập con trỏ toàn cục sshpam_handle của sshd
      • Nếu _pam_add_handler() bị ngắt, trường next chưa khởi tạo có thể còn lại
      • Khi pam_end() được gọi trong SIGALRM handler, nó có thể truyền con trỏ tùy ý cho free()
    • Vì kỹ thuật unlink() cũ của glibc đã bị chặn, phiên bản fastbin của House of Mind trong Malloc Maleficarum được sử dụng
    • Hướng fake arena tới .got.plt của sshd và ghi đè entry _exit() bằng địa chỉ shellcode trên heap
    • Heap của Ubuntu này mặc định có thể thực thi
    • Cần trung bình khoảng 10.000 lần thử
    • Với MaxStartups=10, LoginGraceTime=120, mất trung bình khoảng 1–2 ngày để có root shell từ xa
    • Một kẻ tấn công kém may mắn có thể làm deadlock cả 10 kết nối MaxStartups trước khi lấy được root shell

Thử nghiệm Debian 12.5.0, OpenSSH 9.2p1

  • syslog() và đường đi malloc của glibc

    • Mục tiêu là SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u2, môi trường current stable năm 2024 của Debian 12.5.0
    • Môi trường này dễ bị hồi quy CVE-2006-5051
    • SIGALRM handler của phiên bản này không gọi packet_close() hay pam_end(), mà đi theo đường syslog()
      • grace_alarm_handler() gọi sigdie()
      • sigdie() đi qua sshlogv()do_log() rồi gọi syslog()
    • syslog() của Debian glibc 2.36 gọi malloc ở lần gọi đầu tiên
      • __tzfile_read() được gọi trong đường __localtime64_r()
      • fopen() gọi malloc(304) cho cấu trúc FILE
      • Nó cũng gọi malloc(4096) cho read buffer nội bộ
    • glibc malloc không lấy mandatory lock trong tình huống đơn luồng kể từ tháng 10/2017
    • Trong tiến trình đơn luồng như sshd, khả năng khai thác tranh chấp malloc xuất hiện
  • Điều kiện ASLR và ràng buộc i386

    • Môi trường Debian 12.5.0 i386 có điểm yếu ASLR
    • PIE của sshd, heap, phần lớn thư viện và stack thường được random hóa
    • Bản thân glibc luôn được map tại 0xb7200000 hoặc 0xb7400000
    • Có thể đoán đúng địa chỉ glibc với xác suất một nửa
    • Exploit giả định glibc được map tại 0xb7400000
    • Vì địa chỉ này hơi phổ biến hơn 0xb7200000
  • Trạng thái heap không nhất quán và khai thác cấu trúc FILE

    • Đường malloc được chọn là đường split, chia một free chunk lớn thành hai
    • Sẽ tạo ra chunk được trả về và remainder chunk
    • Nếu SIGALRM chen vào sau khi remainder chunk được nối vào unsorted list nhưng trước khi trường size được khởi tạo, heap sẽ rơi vào trạng thái không nhất quán
    • Kẻ tấn công kiểm soát trường size của remainder chunk thông qua dữ liệu còn sót lại từ heap allocation trước đó
    • Làm remainder chunk lớn hơn thực tế để chồng lấn với heap chunk khác
    • Malloc bên trong SIGALRM handler dùng chunk này và làm ô nhiễm bộ nhớ heap
    • Mục tiêu là cấu trúc FILEfopen() trong __tzfile_read() cấp phát trên heap
      • Với heap corruption hạn chế, ghi đè 1 byte _vtable_offset của cấu trúc FILE
      • Hàm libio của glibc sẽ tìm con trỏ vtable ở offset khác thay vì vị trí mặc định
      • Kẻ tấn công kiểm soát fake vtable pointer và con trỏ _codecvt tại vị trí đó bằng dữ liệu còn sót lại từ heap allocation trước đó
    • Trên glibc i386, kỹ thuật này có thể gọi con trỏ hàm tùy ý __fct trong __fread_unlocked()
    • glibc amd64 dường như không sử dụng _vtable_offset
  • Heap layout và 27 race window

    • Vì khó thắng điều kiện tranh chấp chỉ với một small race window, nghiên cứu tạo 27 cặp large hole và small hole
    • 28 cặp sẽ vượt quá PACKET_MAX_SIZE 256KB
    • Packet cuối cùng buộc thứ tự malloc(~4KB), malloc(304), malloc(~4KB), malloc(304)
    • Nếu mỗi lần split large hole bị ngắt đúng lúc, fopen() trong SIGALRM handler sẽ cấp phát small hole tương ứng làm cấu trúc FILE
    • Để tạo heap layout, mã phân tích khóa công khai của sshd được sử dụng
      • Thực hiện chuỗi malloc()free() gần như tùy ý qua đường cert_parse()cert_free()
      • Vì không tìm được memory leak, tcache chunk được dùng làm barrier chunk tạm thời
    • Gửi năm loại packet khóa công khai
      • a/ Đưa heap allocation không kiểm soát được vào tcache chunk
      • b/ Tạo 27 cặp large/small hole và barrier chunk
      • c/ Ghi sẵn fake header, fake footer, fake vtable và con trỏ _codecvt
      • d/ Cấp phát rồi giải phóng một chuỗi lớn gần 256KB để chuyển các hole từ unsorted list sang từng malloc bin
      • e/ Buộc chuỗi malloc cuối cùng để mở 27 small race window
  • Chiến lược timing cho phiên bản hiện đại

    • Chiến lược timing dựa trên feedback dùng ở phiên bản cũ không hiệu quả với mục tiêu OpenSSH 9.2p1
    • Lần phân tích khóa công khai thứ năm mất khoảng 10ms, khiến large race window quá lớn
    • user_specific_delay() được giới thiệu trong OpenSSH 7.8p1 làm trễ phản hồi tối đa khoảng 9ms, phá vỡ feedback cũ
    • Chiến lược mới so sánh thời gian phản hồi của hai loại lỗi cố ý
      • Gửi packet gây lỗi ngay trước khi phân tích khóa công khai
      • Gửi packet gây lỗi ngay sau khi phân tích khóa công khai
      • Đo thời gian phân tích khóa công khai cuối cùng từ chênh lệch giữa hai thời gian phản hồi
    • Với chiến lược này, thắng điều kiện tranh chấp sau trung bình khoảng 10.000 lần thử
    • Với MaxStartups=100, LoginGraceTime=120, mất trung bình khoảng 3–4 giờ để thắng điều kiện tranh chấp
    • Do ASLR, để có root shell từ xa cần trung bình khoảng 6–8 giờ

Tình trạng exploit amd64

  • Mục tiêu amd64 được chọn là Rocky Linux 9
    • Image mục tiêu là Rocky-9.4-x86_64-minimal.iso
    • OpenSSH 8.7p1 dễ bị điều kiện tranh chấp trong signal handler này
    • Do điểm yếu ASLR, glibc được map theo bội số 2MB, khiến partial pointer overwrite mạnh hơn
  • syslog() của glibc 2.34 trên Rocky Linux 9 gọi nội bộ __open_memstream()
    • Cấp phát cấu trúc FILE trên heap bằng malloc()
    • Cũng gọi calloc(), realloc(), free(), tạo thêm cơ hội
  • Dựa trên primitive heap corruption, hai cấu trúc FILE được cấp phát trên heap, và 21 bit cố định của địa chỉ glibc, nhóm nghiên cứu cho rằng có thể khai thác được cả trên amd64
    • Thời gian dự kiến dài hơn 6–8 giờ của i386, nhưng họ cho biết kỳ vọng dưới một tuần
  • Cũng có quan sát riêng về Ubuntu 24.04
    • Ubuntu 24.04 không random hóa lại ASLR của sshd child mà chỉ random hóa một lần khi boot
    • Nguyên nhân được truy vết tới systemd-socket-activation.patch, vốn tắt rexec_flag
    • Đây thường là một lựa chọn không tốt, nhưng với lỗ hổng này, nó ngăn khai thác vì syslog() trong SIGALRM handler không phải lần gọi syslog() đầu tiên nên không gọi các hàm malloc
    • Bản vá liên quan: https://git.launchpad.net/ubuntu/+source/…

Bản vá và biện pháp giảm thiểu

  • OpenSSH đã sửa điều kiện tranh chấp này bằng commit 81c1099 ngày 6/6/2024
    • 81c1099: thêm chức năng để sshd(8) penalise hành vi client có vấn đề
    • Chuyển mã async-signal-unsafe khỏi SIGALRM handler của sshd sang listener process để xử lý đồng bộ
  • Bản sửa này nằm trên commit lớn 81c1099 và commit defense-in-depth lớn hơn 03e3de4, nên có thể khó backport
  • Nếu khó backport, có thể loại bỏ hoặc chú thích mã async-signal-unsafe trong sshsigdie() để chỉ gọi _exit(1)
  • Nếu không thể cập nhật hoặc biên dịch lại, có thể đặt LoginGraceTime thành 0 trong file cấu hình
    • Thiết lập này chặn thực thi mã từ xa trong advisory này
    • Đổi lại, hệ thống vẫn dễ bị DoS do cạn kiệt toàn bộ kết nối MaxStartups

Lịch công bố

  • 2024-05-19: Liên hệ với nhà phát triển OpenSSH, sau đó lặp lại các vòng vá và review
  • 2024-06-20: Liên hệ distros@openwall
  • 2024-07-01: Công bố theo coordinated release date

1 bình luận

 
GN⁺ 2024-07-02
Ý kiến trên Hacker News
  • Thú vị là bản sửa RCE dường như đã được công khai “trộn” vào gần một tháng trước
    Khi PerSourcePenalties được bật, sshd(8) sẽ theo dõi trạng thái thoát của tiến trình phiên con trước xác thực, và ghi nhận các điều kiện như lỗi xác thực lặp lại hoặc sshd bị crash thành một hình phạt trong một khoảng thời gian đối với địa chỉ client
    https://github.com/openssh/openssh-portable/commit/81c1099d2...
    Có vẻ đây không phải là một bản vá có thể bị reverse-engineer để tiết lộ điều gì đó cho kẻ tấn công, mà khá thông minh vì nó thay đổi cấu trúc binary, loại bỏ lỗ hổng cụ thể và như một tác dụng phụ còn giảm thiểu cả nhóm exploit đó

    • Đó không phải là bản sửa RCE; bản sửa RCE thật sự là ở đây: https://news.ycombinator.com/item?id=40843865
      Thay đổi ở trên là một tính năng đã được báo trước để xử lý các kết nối rác, và chỉ giảm thiểu lỗ hổng này bằng cách khiến việc thắng race condition khó hơn
      Thảo luận trước đó: https://news.ycombinator.com/item?id=40610621
    • Không biết bản sửa này đã được đưa vào hoặc được các bản phân phối lấy về chưa
    • Thật thú vị là bình luận này sai và đã được đính chính ngay bên dưới, vậy mà vẫn nằm trên cùng suốt 2 ngày
      Không biết có phải mọi người chỉ đọc bình luận đầu tiên của thread, upvote rồi rời đi với ấn tượng sai hay không
  • Một đoạn trong ghi chú phát hành của OpenSSH khá đáng chú ý
    “Việc khai thác thành công đã được chứng minh trên các hệ thống Linux/glibc 32-bit có bật ASLR. Trong điều kiện phòng thí nghiệm, cuộc tấn công cần duy trì các kết nối liên tiếp ở mức tối đa mà máy chủ cho phép trong trung bình 6–8 giờ. Người ta tin rằng điều này cũng khả thi trên hệ thống 64-bit, nhưng chưa được chứng minh. Các cuộc tấn công như vậy nhiều khả năng sẽ được cải thiện.”
    https://www.openssh.com/releasenotes.html

  • Nhìn vào diff [1] đã đưa bug vào, theo phân tích thì vấn đề là trong quá trình refactor từ dạng sigdie() được bọc bằng #ifdef DO_LOG_SAFE_IN_SIGHAND sang dạng sshsigdie() gọi trực tiếp sshlogv(), #ifdef đã bị bỏ sót
    Điều gì có thể ngăn được chuyện này? Có lẽ cần xem pull request kỹ hơn? Thật ngạc nhiên khi phần mềm mà cả thế giới dựa vào để kết nối bảo mật có vẻ trên thực tế chỉ do hai người [2] bảo trì
    [1] https://github.com/openssh/openssh-portable/commit/752250caa...
    [2] https://github.com/openssh/openssh-portable/graphs/contribut...

    • Nhìn lại sau sự việc thì rất dễ nói đáng ra làm gì để ngăn chặn
      Trong trường hợp này, nếu có chú thích giải thích vì sao cần #ifdef thì có thể đã hữu ích. Ví dụ như “mã ở đây phải an toàn với tín hiệu bất đồng bộ, và trạng thái khóa có thể không xác định”
      Dù vậy, nói thật thì getrlimit cũng không nằm trong danh sách này: https://man7.org/linux/man-pages/man7/signal-safety.7.html
      Nhưng nếu mã có chú thích liên quan đến an toàn với tín hiệu bất đồng bộ bị xóa hoặc sửa, khả năng cao điều đó sẽ bị chú ý khi review. Trong đoạn mã được trích, chỉ có SAFE_IN_SIGHAND phần nào gợi ý rằng mã này phải an toàn khi chạy trong signal handler
    • Vì OpenBSD đã refactor hệ thống để dùng hàm syslog reentrant an toàn với tín hiệu bất đồng bộ, có thể người viết đoạn mã này chỉ đơn giản giả định rằng thay đổi là an toàn
      Họ có thể đã quên hoặc không biết rằng trên các nền tảng khác, vốn các nhà phát triển ssh của OpenBSD không thực sự tuyên bố hỗ trợ, vẫn dùng các hàm không an toàn với tín hiệu bất đồng bộ
    • Đây là mã nguồn mở. Nếu cảm thấy có thể làm tốt hơn thì cứ fork tùy ý
      Bạn không có quyền đòi hỏi nhận được điều gì từ các nhà phát triển mã nguồn mở. Họ cũng có thể mắc lỗi, và họ có quyền tự quyết có bao nhiêu maintainer hay reviewer
      https://gist.github.com/richhickey/1563cddea1002958f96e7ba95...
    • Câu “phần mềm mà cả thế giới dựa vào để kết nối bảo mật trên thực tế do hai người bảo trì” bắt buộc khiến người ta nhớ đến xkcd này: https://xkcd.com/2347/
    • Có vài cách có thể ngăn được chuyện này
      1. Dùng một ngôn ngữ lập trình tử tế không cho đặt hàm tùy ý làm signal handler. Trong libc thông thường thì điều đó rõ ràng là không an toàn, còn trong Rust hoặc Java an toàn thì không thể làm như vậy
      2. Dùng một libc được triển khai tốt, trong đó việc gọi hàm không an toàn với tín hiệu bất đồng bộ chỉ gây deadlock ở mức nào đó chứ không gây hỏng bộ nhớ. Điều này tương đối dễ nếu xem mã chạy bên trong signal như một thread riêng về mặt truy cập thread-local storage; cũng có thể tránh deadlock nếu không có mutex toàn cục hoặc có thể tiếp tục đoạn mã bị ngắt khi đang giữ mutex
      3. Suy nghĩ khi thay đổi và phê duyệt mã. Đừng như những người đã bỏ #ifdef không có căn cứ như trong [1]
      4. Dùng phần mềm đơn giản, được thiết kế tốt do lập trình viên giỏi viết thay cho OpenSSH
  • Ghi chú phát hành cũng đáng đọc: https://www.openssh.com/releasenotes.html
    Đây thực ra là một biến thể của lỗi race condition liên quan đến signal khá thú vị. Theo báo cáo lỗ hổng, “OpenBSD đặc biệt không bị ảnh hưởng, vì handler SIGALRM gọi syslog_r(), một phiên bản syslog() an toàn hơn với signal bất đồng bộ mà OpenBSD tạo ra vào năm 2001”
    Tức là biện pháp giảm thiểu về an toàn signal đã khiến các nhà phát triển OpenBSD đưa những đoạn code không hề tầm thường vào trong signal handler, và khi code đó được port sang các hệ thống khác thì nó trở nên không an toàn. Nếu họ refactor để giữ code trong signal handler ở mức tối thiểu theo hiểu biết phổ biến và quy ước code Unix, lỗi này có lẽ đã tránh được

    • Theo de Raadt đã đưa ra một nhận xét khá hợp lý về việc phòng tránh lỗi này và các lỗi tương tự: không signal handler nào được gọi các hàm không phải là system call an toàn với signal
      Vì theo thời gian, rất dễ để một lời gọi không an toàn với signal bất đồng bộ lọt vào đâu đó trong chuỗi gọi chuyển tiếp, và cũng không phải lúc nào cũng rõ rằng đường đi đó có thể được chạm tới từ ngữ cảnh signal
    • Khả năng là có khá nhiều quản trị viên hệ thống trẻ hoặc thực tập sinh phải vá lỗ hổng này còn chưa ra đời khi OpenBSD triển khai cách khắc phục đó
  • Sau khi nâng cấp các instance OpenSSH của mình, tôi thấy chúng được link với musl chứ không phải glibc, nên đã xem thử syslog(3) của musl có cấp phát bộ nhớ không, và do đó có dễ bị khai thác theo cùng cách hay không
    Nhìn qua thì có vẻ là không: https://github.com/bminor/musl/blob/master/src/misc/syslog.c
    Tất cả những gì ở đó đều là biến trên stack hoặc biến static được khóa để ngăn tái nhập. Các lời gọi {d,sn,vsn}printf() trong musl cũng không cấp phát, nhưng trong glibc thì có thể. Tôi có bỏ sót gì không?

    • Xác nhận của Rich: https://fosstodon.org/@musl/112711796005712271
    • Nếu nhận định về việc cấp phát là đúng, kịch bản tệ nhất có lẽ chỉ là deadlock vì lock không có tính đệ quy
      Tuy vậy, deadlock trong sigalrm vẫn có thể ngăn việc dọn dẹp kết nối, dẫn đến từ chối dịch vụ
  • Đã có bản vá cho FreeBSD
    Chưa rõ có bị ảnh hưởng hay không. Cách khai thác đã biết chỉ khả thi trên glibc, và FreeBSD không dùng glibc, nhưng cẩn thận vẫn hơn
    https://www.freebsd.org/security/advisories/FreeBSD-SA-24:04...

  • Theo báo cáo, nếu không thể cập nhật hoặc biên dịch lại sshd, chỉ cần đặt LoginGraceTime thành 0 trong file cấu hình là có thể sửa race condition trong signal handler này
    Trong trường hợp đó, sshd sẽ dễ bị từ chối dịch vụ do cạn kiệt mọi kết nối MaxStartups, nhưng sẽ an toàn trước lỗi thực thi mã từ xa được nêu trong khuyến cáo này
    Vì vậy, có vẻ đặt LoginGraceTime 0 trong sshd_config là một biện pháp giảm thiểu

    • Khoan đã, https://www.man7.org/linux/man-pages/man5/sshd_config.5.html nói rằng giá trị 0 nghĩa là không có giới hạn thời gian
      Vậy chẳng phải còn tệ hơn sao?
    • Một workaround thực tế hơn có thể là đặt thời gian chờ đủ dài, hoặc ngược lại điều chỉnh số kết nối tối đa để xác suất tấn công thành công bị đẩy xa đến mức không đáng thử
    • Việc cold restart sshd mỗi giờ có thể giảm khả năng bị khai thác hoặc khiến việc khai thác khó hơn không?
  • Đã có bản vá cho Debian 12, còn Debian 11 không bị ảnh hưởng
    https://security-tracker.debian.org/tracker/CVE-2024-6387

    • Focal (20.04) có vẻ không phải phiên bản bị ảnh hưởng, còn Jammy (22.04) thì có vẻ bị ảnh hưởng
    • Tôi vừa chạy apt updateupgrade trên server Debian 12, và chỉ có các gói OpenSSH được nâng cấp
    • Đã xác nhận Pi OS bullseye cũng nhận được openssh đã cập nhật
  • Phát hiện thật sự rất hay
    Dù không phải người trực tiếp làm công việc này, tôi thường có cảm giác trong nghiên cứu bảo mật, để “thắng” thì không phải chỉ tìm và sửa một vấn đề đơn lẻ, hay nhận thưởng cho nó, mà phải tìm ra toàn bộ chuỗi dẫn tới truy cập từ xa
    Tôi nghĩ lẽ ra chỉ cần tìm được một lỗ hổng đơn lẻ, chẳng hạn một lỗi hỏng bộ nhớ hoặc một lỗi thoát sandbox, đã phải là đủ rồi. Hiện nay có quá nhiều vấn đề nhỏ, nên có lẽ để mọi người thật sự nghiêm túc xem xét hoặc trả bug bounty, bạn phải cho thấy một vụ hack đi được đến tận cùng

    • Có nhiều người muốn trở thành nhà nghiên cứu bảo mật tìm ra những vấn đề không thể khai thác rồi đòi số CVE, sự công nhận, thậm chí cả tiền thưởng
      Ví dụ, nếu một ứng dụng bị crash khi nhận đầu vào tin cậy sai, nhưng xét theo tính chất của ứng dụng đó, nó không được thiết kế để lộ ra trước kẻ đối địch và trên thực tế cũng không có khả năng như vậy, thì đa số sẽ chỉ xem đó là bug chứ không phải bug bảo mật. Sửa được thì tốt, nhưng không cùng cấp độ, và những lỗi kiểu này cũng không quá khó tìm
      Vì vậy cần phân biệt giữa bug bảo mật “thật” như trường hợp này với những bug không có tác động bảo mật, và việc chứng minh vấn đề có thể bị khai thác là cực kỳ quan trọng
      Sẽ luôn có vô số bug không có tác động bảo mật, nên tôi không nghĩ yêu cầu chứng minh kiểu này sẽ sớm biến mất
    • Nhìn từ một góc khác, giả sử tôi tạo ra một thư viện tuần tự hóa/giải tuần tự hóa sẽ trở nên dễ tổn thương nếu tôi đưa dữ liệu không đáng tin cậy vào
      Đó là do thiết kế, và người dùng có thể tuần tự hóa cũng như giải tuần tự hóa bất cứ thứ gì, kể cả hàm lambda. Thư viện của tôi chỉ được dự định để xử lý dữ liệu từ nguồn đáng tin cậy
      Theo tôi biết, không ai dùng thư viện này để xử lý dữ liệu không đáng tin cậy. Một thư viện phổ biến có dùng thư viện của tôi để đọc tệp cấu hình, nhưng họ xem tệp cấu hình là dữ liệu đáng tin cậy. Và việc kiểm soát người khác dùng thư viện của tôi như thế nào không phải việc của tôi
      Trong trường hợp này, có đúng không nếu đăng ký một CVE mức ưu tiên cao nhất với lý do dự án của tôi có lỗ hổng thực thi mã từ xa?
    • Tôi từng ở phía người báo cáo, và “lỗ hổng có thể khai thác” rất khác với “điểm yếu bảo mật một ngày nào đó có thể dẫn tới lỗ hổng có thể khai thác”
      Tiền thưởng luôn được trả cho nhóm thứ nhất. Báo cáo thuộc nhóm thứ hai, nếu không có bằng chứng khái niệm hoặc chứng minh khả năng khai thác, thậm chí có thể làm hại uy tín hoặc tín hiệu của bạn
      Các điểm yếu chỉ trở nên khai thác được khi một số điều kiện cụ thể được đáp ứng gần như luôn tồn tại. Ngay cả trong các cuộc thi như Pwn2Own, người ta cũng thường thấy nhiều lỗ hổng được nối lại để cuối cùng chiếm quyền thiết bị, rồi sau đó vẫn không được vá trong nhiều năm. Các nhà nghiên cứu đôi khi cũng giữ những điểm yếu đó rất lâu để tối đa hóa mức độ tác động
      Đáng buồn là thực tế là vậy
    • Theo châm ngôn bảo mật thì: POC || GTFO
    • Người mua trả tiền cho kết quả. Nhà cung cấp thì cũng trả tiền cho từng mắt xích riêng lẻ trong chuỗi
  • Ghi chú phát hành OpenSSH: https://www.openssh.com/txt/release-9.8
    Bản vá tối thiểu cho những ai không thể hoặc không muốn nâng cấp: https://marc.info/?l=oss-security&m=171982317624594&w=2

    • “Việc khai thác trên hệ thống 64-bit cũng được cho là có thể, nhưng tại thời điểm hiện tại chưa được chứng minh”