Bảo mật nghiêm túc: GnuTLS tuân theo OpenSSL, sửa lỗi tấn công theo thời gian

Bảo mật nghiêm túc: GnuTLS tuân theo OpenSSL, sửa lỗi tấn công theo thời gian

Nút nguồn: 1956368

Tuần trước, chúng tôi đã viết về một loạt lỗi quản lý bộ nhớ đã được sửa trong bản cập nhật bảo mật mới nhất của thư viện mã hóa OpenSSL phổ biến.

Cùng với những lỗi bộ nhớ đó, chúng tôi cũng đã báo cáo về một lỗi có tên CVE-2022-4304: Định thời gian Oracle trong giải mã RSA.

Trong lỗi này, lặp đi lặp lại cùng một thông báo được mã hóa tại một máy chủ, nhưng sửa đổi phần đệm ở cuối dữ liệu để làm cho dữ liệu không hợp lệ và do đó gây ra một số loại hành vi không thể đoán trước…

…sẽ không mất nhiều thời gian nhất quán, giả sử bạn đã ở gần mục tiêu trên mạng và bạn có thể đoán chắc chắn phần chuyển dữ liệu của quy trình sẽ mất bao lâu.

Không phải tất cả dữ liệu được xử lý như nhau

Nếu bạn thực hiện một yêu cầu, hãy tính thời gian trả lời mất bao lâu và trừ đi thời gian tiêu tốn trong quá trình gửi và nhận dữ liệu mạng ở mức độ thấp, bạn sẽ biết máy chủ mất bao lâu để thực hiện tính toán nội bộ của mình để xử lý yêu cầu .

Ngay cả khi bạn không chắc chắn đã sử dụng bao nhiêu thời gian trong mạng, bạn có thể tìm kiếm các biến thể về thời gian khứ hồi bằng cách thực hiện nhiều yêu cầu và thu thập vô số mẫu.

Nếu mạng đủ tin cậy để giả định rằng chi phí mạng phần lớn không đổi, bạn có thể sử dụng các phương pháp thống kê để suy ra loại sửa đổi dữ liệu nào gây ra loại độ trễ xử lý bổ sung nào.

Từ đó, bạn có thể suy ra điều gì đó về cấu trúc hoặc thậm chí là nội dung của dữ liệu ban đầu không được mã hóa vốn được cho là được giữ bí mật bên trong mỗi yêu cầu được lặp lại.

Ngay cả khi bạn chỉ có thể trích xuất một byte văn bản gốc, điều đó sẽ không xảy ra.

Cái gọi là thời gian tấn công loại này luôn rắc rối, ngay cả khi bạn có thể cần phải gửi hàng triệu gói không có thật và định thời gian cho tất cả chúng để có bất kỳ cơ hội nào khôi phục chỉ một byte dữ liệu văn bản gốc…

…vì mạng nhanh hơn, dễ dự đoán hơn và có khả năng xử lý nhiều tải hơn so với cách đây vài năm.

Bạn có thể nghĩ rằng hàng triệu gói dữ liệu nguy hiểm đã gửi thư rác cho bạn trong một giờ tới sẽ nổi bật như ngón tay cái.

Nhưng “nhiều hơn hoặc ít hơn một triệu gói một giờ so với bình thường” đơn giản không còn là một biến thể đặc biệt lớn nữa.

Lỗi "tiên tri" tương tự trong GnuTLS

Chà, chính người đã báo cáo lỗi thời gian sửa lỗi cuối cùng trong OpenSSL cũng đã báo cáo một lỗi tương tự trong GnuTLS tại cùng một thời điểm.

Cái này có định danh lỗi CVE-2023-0361.

Mặc dù GnuTLS không phổ biến hoặc được sử dụng rộng rãi như OpenSSL, nhưng bạn có thể có một số chương trình trong khu vực CNTT của mình hoặc thậm chí trên máy tính của riêng bạn sử dụng hoặc bao gồm nó, có thể bao gồm FFmpeg, GnuPG, Mplayer, QEMU , Rdesktop, Samba, Wget và Wireshark.

Trớ trêu thay, lỗ hổng thời gian trong GnuTLS lại xuất hiện trong đoạn mã được cho là ghi lại các lỗi tấn công thời gian ngay từ đầu.

Như bạn có thể thấy từ sự khác biệt về mã (khác) bên dưới, lập trình viên đã biết rằng bất kỳ (if ... then) được sử dụng để kiểm tra và xử lý lỗi giải mã có thể tạo ra các biến thể về thời gian, bởi vì CPU thường mất một khoảng thời gian khác nhau tùy thuộc vào cách mã của bạn chạy sau lệnh "nhánh".

(Điều đó đặc biệt đúng đối với một nhánh thường đi theo một hướng và hiếm khi đi theo hướng khác, bởi vì CPU có xu hướng ghi nhớ hoặc lưu vào bộ đệm, mã chạy lặp lại để cải thiện hiệu suất, do đó làm cho mã không được sử dụng thường xuyên chạy chậm hơn đáng kể.)

Mã khác của gnutls-3.7.8/lib/auth/rsa.c so với 3.7.9

Nhưng lập trình viên vẫn muốn ghi lại rằng một cuộc tấn công có thể đang xảy ra, điều này xảy ra nếu if (ok) kiểm tra ở trên không thành công và phân nhánh vào else { ... } phần.

Tại thời điểm này, mã gọi _gnutls_debug_log() chức năng, có thể mất khá nhiều thời gian để thực hiện công việc của nó.

Do đó, người mã hóa đã chèn một cuộc gọi có chủ ý đến _gnutls_no_log() trong then { ... } một phần của mã, giả vờ ghi lại một “cuộc tấn công” khi không có, để cố gắng tăng thời gian mà mã dành cho một trong hai hướng mà mã if (ok) hướng dẫn chi nhánh có thể mất.

Tuy nhiên, rõ ràng là hai đường dẫn mã không đủ giống nhau trong thời gian chúng sử dụng hết (hoặc có lẽ _gnutls_debug_log() tự nó không đủ nhất quán trong việc xử lý các loại lỗi khác nhau) và kẻ tấn công có thể bắt đầu phân biệt các câu chuyện giải mã sau một triệu lần thử.

Phải làm gì?

Nếu bạn là một lập trình viên: cách sửa lỗi ở đây rất đơn giản và tuân theo nguyên tắc “ít hơn là nhiều hơn”.

Mã màu hồng ở trên, được coi là không cung cấp dữ liệu phát hiện tấn công cực kỳ hữu ích, đã bị xóa đơn giản, với lý do mã không có ở đó không thể được biên dịch do nhầm lẫn, bất kể cài đặt bản dựng của bạn là gì…

…và mã không được biên dịch không bao giờ có thể chạy, dù là do ngẫu nhiên hay do thiết kế.

Nếu bạn là người dùng GnuTLS: phiên bản mới phát hành 3.7.9 và “hương vị sản phẩm mới” 3.8.0 có bản sửa lỗi này, cùng với nhiều bản sửa lỗi khác.

Nếu bạn đang chạy một bản phân phối Linux, hãy kiểm tra các bản cập nhật cho bất kỳ phiên bản thư viện dùng chung được quản lý tập trung nào của GnuTLS mà bạn có, cũng như các ứng dụng mang theo phiên bản của riêng chúng.

Trên Linux, tìm kiếm các tệp có tên libgnutls*.so để tìm bất kỳ thư viện dùng chung nào xung quanh và tìm kiếm gnutls-cli để tìm bất kỳ bản sao nào của tiện ích dòng lệnh thường có trong thư viện.

Bạn có thể chạy gnutls-cli -vv để tìm ra phiên bản nào của libgnutls nó được liên kết động với:

 $ gnutls-cli -vv gnutls-cli 3.7.9 <- bản phân phối Linux của tôi đã nhận được bản cập nhật vào thứ Sáu tuần trước (2023-02-10)

Dấu thời gian:

Thêm từ An ninh trần trụi