2 điểm bởi GN⁺ 2025-01-10 | 1 bình luận | Chia sẻ qua WhatsApp

WorstFit: Tiết lộ các bộ chuyển đổi ẩn trong Windows ANSI

TL;DR

  • Đã phát hiện một bề mặt tấn công mới bằng cách lợi dụng Best-Fit, tính năng chuyển đổi bảng mã nội bộ của Windows.
  • Đã biến chức năng này thành các cuộc tấn công thực tế như path traversal, injection đối số và thực thi mã từ xa (RCE).
  • Nguyên nhân gốc rễ nằm ở hành vi của trình biên dịch, runtime C/C++, và lỗi của nhà phát triển.
  • Cũng thảo luận về độ khó khi áp dụng bản vá trong hệ sinh thái mã nguồn mở.

Giải mã mã hóa Windows

Khởi đầu: ANSI và trang mã

  • Ban đầu Windows dùng mã hóa ANSI, hiệu quả cho một ngôn ngữ nhất định nhưng không xử lý được các bộ ký tự hỗn hợp.
  • Có nhiều trang mã, mỗi trang mã hỗ trợ một ngôn ngữ cụ thể.

Thời kỳ Unicode: UTF-16

  • Vào giữa những năm 1990, Windows chuyển sang Unicode để biểu diễn gần như mọi ký tự của hầu hết ngôn ngữ theo một chuẩn thống nhất.
  • Ban đầu sử dụng UCS-2, nhưng đã nhanh chóng nâng cấp lên UTF-16.

Thời kỳ mã hóa kép

  • Để tương thích với các trang mã ANSI trước đây, Windows đã triển khai hai phiên bản API.
  • Với cả ANSI APIUnicode API, nhà phát triển có thể dễ dàng lấy được định dạng dữ liệu mong muốn.

Ưu điểm của Best-Fit

  • Chuyển đổi ký tự "Best-Fit" của Windows là cơ chế xử lý ký tự không có trong trang mã đích khi chuyển đổi từ UTF-16 sang ANSI.
  • Ví dụ, ký hiệu không có trong mã trang Windows-1252, vì vậy Microsoft ánh xạ nó thành 8.

WorstFit: bề mặt tấn công mới của Windows

🔥 Cơn ác mộng châu Á - CVE-2024-4577

  • CVE-2024-4577 là lỗ hổng cho phép khai thác máy chủ PHP-CGI dùng bảng mã tiếng Trung hoặc tiếng Nhật bằng một yêu cầu ?%ADs đơn giản.
  • Do hành vi Best-Fit, U+00AD (dấu nối mềm) bị ánh xạ thành dấu gạch ngang (-), nên có thể vượt qua cơ chế bảo vệ.

🔥 Tàng hình tên tệp

  • Có thể lợi dụng WorstFit trong xử lý tên tệp để chuyển thành payload path traversal.
  • Ví dụ, Chrome V8 Developer Shell (d8.exe) dùng ANSI API để lấy thư mục làm việc hiện tại.

🔥 Tách đối số

  • Có thể thao túng đầu ra của GetCommandLineA để lợi dụng hành vi WorstFit cho phân tích cú pháp dòng lệnh.
  • Ví dụ, đầu vào " --use-askpass=calc " có thể khiến hệ thống thực thi calc.exe.

Kết luận

  • Hành vi Best-Fit tạo bề mặt tấn công ở lớp chuyển đổi cấp hệ thống, có thể gây ra lỗ hổng trong nhiều công cụ.
  • Các hàm trong thư viện chuẩn hoặc ngôn ngữ lập trình không thể chặn hoàn toàn các cuộc tấn công này.

1 bình luận

 
GN⁺ 2025-01-10
Ý kiến Hacker News
  • Microsoft đã biết về vấn đề này từ ít nhất một năm trước. Thông qua quy tắc phân tích mã CA2101 đặc biệt, họ không khuyến nghị sử dụng ánh xạ best-fit. Họ có nhắc đến lỗ hổng bảo mật nhưng chi tiết còn mơ hồ

  • Đây là vấn đề mang tính hệ thống. Microsoft cung cấp ánh xạ mã "best fit" để chuyển đổi Unicode sang ASCII. Ánh xạ này được dùng trong rất nhiều chỗ và do Microsoft coi trọng khả năng tương thích ngược nên vẫn cần giữ lại. Về cơ bản nó được liên kết mặc định ở tất cả nơi

    • Chủ yếu bị lạm dụng bằng cách chuyển đổi các điểm mã bất thường thành slash, dấu gạch ngang, dấu nháy... Trong các ngôn ngữ lập trình hiện đại chúng thường được đánh giá đúng, nhưng khi truyền vào lệnh shell hoặc Win32 API thì lại gây lỗi

    • Người bảo trì curl nói rằng "curl là nạn nhân", nhưng nguyên nhân thực sự nằm ở chỗ khác. Vấn đề phát sinh khi đầu vào của máy chủ được xác thực và khi áp dụng cho thư viện hệ thống theo hai cách khác nhau

    • Việc tắt chọn lọc best-fit trong không gian Win32 có thể là một giải pháp. Các nhà cung cấp mã nguồn mở có thể thêm điều này vào các best practice

  • Windows giống như một ván Munchkin, nhiều tính năng tình cờ kết hợp khiến ra lỗ hổng rất mạnh. Việc chuyển đổi hệ thống con ANSI của Windows sang UTF-8 có thể giảm bớt vấn đề này

  • Từ NT 3.5, Microsoft đã dần loại bỏ ANSI và thúc đẩy việc dùng Wide Character API. Tuy nhiên, cách triển khai trong thư viện C/C++ runtime của Microsoft là trở ngại chính

    • Hàm chuẩn thường dùng hàm A và sử dụng phương pháp best-fit để chuyển đổi Unicode mà không báo lỗi khi chuyển đổi thất bại
  • Khả năng Microsoft bật UTF-8 mặc định cho mọi bản Windows là thấp, vì các ứng dụng cũ phụ thuộc vào một số trang mã hoặc ký tự 1-byte

    • Việc gỡ bỏ logic Best-Fit khỏi API win32 xxxA có thể tạo ít vấn đề hơn
  • Có hai cách buộc ứng dụng thiết lập trang mã "Ansi" thành UTF-8. Một cách là dùng tệp Manifest, cách khác là dùng công cụ "App Locale"

  • Trên máy Windows cá nhân, mình bật chế độ UTF-8 và điều này khiến bản thân an toàn trước bug này. Mình đã bật vì game nước ngoài cũ bị lỗi hiển thị chữ

  • Khắc phục không chỉ là thay main() bằng phiên bản wide-character. Cần chuyển tất cả biến sang wchar_t * và việc này rất đau đầu, dễ lỗi

    • Thay vào đó, ta có thể chuyển các ký tự wide nhận được sang UTF-8 và tiếp tục dùng char. Hãy cẩn thận không trộn chuỗi ANSI hoặc OEMCP với chuỗi UTF-8
  • Mình biết Windows API có cung cấp best-fit conversion nhưng không nhận ra đây là hành vi mặc định. Chức năng này phải bị cấm

  • Tự hỏi ô đánh dấu beta có tương đương với việc đặt ActiveCodePage là UTF-8 không. GDI không theo code page theo từng tiến trình mà theo code page toàn cục. Thật đáng tiếc là không thể chọn UTF-8 hoàn toàn