Tóm tắt
- Phát hiện lỗ hổng bảo mật trong OpenSSH: Phát hiện lỗ hổng thực thi mã từ xa (RCE) trong máy chủ OpenSSH (
sshd) do điều kiện tranh chấp trong trình xử lý tín hiệu. Lỗ hổng này ảnh hưởng đến sshd ở cấu hình mặc định.
- Nguồn gốc của lỗ hổng: Đây là sự tái xuất hiện của CVE-2006-5051, từng được báo cáo vào năm 2006, phát sinh do thay đổi mã được đưa vào OpenSSH 8.5p1 vào tháng 10 năm 2020.
- Tác động của lỗ hổng: Có thể bị khai thác từ xa trên các hệ thống Linux dựa trên glibc, ảnh hưởng đến mã đặc quyền của
sshd, cho phép thực thi mã từ xa với quyền root.
- Cách khai thác lỗ hổng: Để khai thác lỗ hổng này cần tìm được đường đi mã cụ thể và ngắt nó đúng thời điểm. Việc nghiên cứu bắt đầu từ các phiên bản OpenSSH cũ rồi mở rộng sang các phiên bản mới nhất.
- Bản vá và biện pháp giảm thiểu: Cung cấp bản vá và các biện pháp giảm thiểu để xử lý lỗ hổng.
SSH-2.0-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3 (Debian 3.0r6, năm 2005)
Lý thuyết
- Trình xử lý SIGALRM: Trình xử lý SIGALRM của phiên bản này gọi
packet_close(), hàm này gọi buffer_free(), rồi tiếp tục gọi xfree() và free(). free() không an toàn với tín hiệu bất đồng bộ.
- Phân tích mã malloc: Trong mã malloc, đã tìm thấy đường đi có thể khai thác lỗ hổng khi lời gọi
free() bị ngắt bởi SIGALRM và sau đó được gọi lại bên trong trình xử lý SIGALRM.
Thực hành
- Phương pháp tấn công: Ngắt lời gọi
free() trong đoạn mã phân tích khóa công khai DSA, rồi khai thác điều này bên trong trình xử lý SIGALRM để đạt được thực thi mã từ xa.
- Thắng điều kiện tranh chấp: Cần khoảng 10.000 lần thử để thắng điều kiện tranh chấp này, trung bình mất khoảng 1 tuần.
Thời điểm
- Chiến lược canh thời gian: Để giảm độ trễ mạng, gửi byte cuối cùng vào đúng khoảnh khắc cuối và theo dõi thời gian khứ hồi để điều chỉnh thời điểm. Nhờ đó tăng xác suất thắng điều kiện tranh chấp.
SSH-2.0-OpenSSH_4.2p1 Debian-7ubuntu3 (Ubuntu 6.06.1, năm 2006)
Lý thuyết lần 1
- Trình xử lý SIGALRM: Trình xử lý SIGALRM của phiên bản này không gọi
packet_close(), và do hàm malloc luôn khóa nên cần một hướng giải quyết khác.
- Sử dụng PAM: Phát hiện
pam_end() của PAM không an toàn với tín hiệu bất đồng bộ và tìm kiếm đường đi có thể khai thác điều này.
Lý thuyết lần 2
- Phân tích
pam_start(): Nếu pam_start() bị ngắt, cấu trúc PAM có thể bị để lại ở trạng thái không nhất quán, và điều này có thể bị khai thác bên trong trình xử lý SIGALRM.
- Kỹ thuật House of Mind: Sử dụng kỹ thuật House of Mind để thao túng cấp phát bộ nhớ nhằm đạt được thực thi mã từ xa với quyền root.
Thực hành
- Phương pháp tấn công: Dùng tên người dùng dài để thao túng cấp phát bộ nhớ và tăng xác suất thắng điều kiện tranh chấp thông qua nhiều lần gọi
pam_start().
Thời điểm
- Chiến lược canh thời gian: Tái sử dụng chiến lược canh thời gian đã dùng ở phiên bản Debian trước để tăng xác suất thắng điều kiện tranh chấp. Trung bình mất 1-2 ngày.
SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u2 (Debian 12.5.0, năm 2024)
Lý thuyết
- Trình xử lý SIGALRM: Trình xử lý SIGALRM của phiên bản này gọi
syslog(), hàm này lại gọi các hàm không an toàn với tín hiệu bất đồng bộ.
- Phân tích glibc:
syslog() của glibc gọi malloc, vốn không an toàn với tín hiệu bất đồng bộ. Ngoài ra, hàm malloc của glibc không khóa khi chạy đơn luồng.
Bản vá và biện pháp giảm thiểu
- Bản vá: Đã báo cáo lỗ hổng cho các nhà phát triển OpenSSH và cung cấp bản vá để khắc phục.
Ý kiến của GN⁺
- Tầm quan trọng của bảo mật: OpenSSH là phần mềm bảo mật cực kỳ quan trọng, và đây là một trường hợp rất hiếm gặp của lỗ hổng kiểu này.
- Độ khó khi khai thác lỗ hổng: Việc khai thác lỗ hổng này đòi hỏi canh thời gian cực kỳ tinh vi và rất nhiều lần thử.
- Giải pháp thay thế: Ngoài OpenSSH còn có nhiều giải pháp bảo mật khác, và nên sử dụng kết hợp chúng.
- Thách thức kỹ thuật: Nghiên cứu này đòi hỏi trình độ kỹ thuật rất cao và có thể mang lại nhiều cảm hứng cho các nhà nghiên cứu bảo mật.
- Giảm thiểu lỗ hổng: Điều quan trọng là áp dụng các bản vá bảo mật mới nhất và tăng cường cấu hình bảo mật.
1 bình luận
Ý kiến trên Hacker News
Bản sửa lỗi RCE đã được công khai một cách gần như "âm thầm" từ gần một tháng trước
sshd(8)sẽ theo dõi trạng thái kết thúc của các tiến trình phiên con trước xác thựcsshdbị crashTrong diff đã đưa bug vào, hàm được refactor như sau
sigdie(const char *fmt,...)sshsigdie(const char *file, const char *func, int line, const char *fmt, ...)#ifdefMột bình luận thú vị trong ghi chú phát hành OpenSSH
OpenBSD không bị ảnh hưởng bởi lỗ hổng này vì trình xử lý SIGALRM gọi
syslog_r()syslog()an toàn với tín hiệu bất đồng bộKhi xem xét
syslog(3)của musl, có vẻ nó không dễ bị khai thác như glibcĐã có bản vá cho FreeBSD, và do không dùng glibc nên nhiều khả năng không bị ảnh hưởng
Có thể giảm thiểu vấn đề bằng cách đặt
LoginGraceTime 0trong tệpsshd_configĐã có bản vá cho Debian 12, còn Debian 11 không bị ảnh hưởng
Có cung cấp liên kết đến ghi chú phát hành OpenSSH và bản vá tối thiểu
Từ góc nhìn độc lập, chỉ cần tìm ra một lỗ hổng đơn lẻ lẽ ra đã phải là đủ