1 điểm bởi GN⁺ 2025-07-09 | 1 bình luận | Chia sẻ qua WhatsApp
  • Giới thiệu kỹ thuật tấn công sử dụng ký tự carriage return trong kho Git
  • Lỗ hổng này có thể dẫn tới khả năng thực thi mã từ xa (RCE)
  • Trong một số quy trình git clone nhất định, lệnh độc hại có thể bị thực thi
  • Đã xác nhận ảnh hưởng trên môi trường Linux và Windows
  • Nhấn mạnh rủi ro của việc quản lý kho Git kém an toàn

Ký tự carriage return và lỗ hổng Git

  • Có thể tạo tên tệp chứa ký tự carriage return (\r) bên trong kho Git
  • Khi sao chép một kho chứa các tên tệp như vậy bằng git clone, trong quá trình diễn giải lệnh có thể xảy ra việc thực thi lệnh ngoài ý muốn

Kịch bản thực thi mã từ xa (RCE)

  • Kẻ tấn công thêm một tệp có chèn ký tự carriage return rồi commit vào kho
  • Khi người dùng git clone kho này, do hệ thống tệp và lệnh git diễn giải sai, sẽ phát sinh nguy cơ thực thi mã không mong muốn
  • Đặc biệt, có thể dẫn dụ để script hook (ví dụ: mã trong thư mục .git/hooks) được tự động chạy

Môi trường bị ảnh hưởng và cách ứng phó

  • Có thể xảy ra trên git của nhiều hệ điều hành khác nhau như Linux và Windows
  • Đây là mối đe dọa bảo mật nghiêm trọng đối với các nhà phát triển và doanh nghiệp quản lý kho git hoặc thường xuyên clone kho bên ngoài

Khuyến nghị bảo mật

  • Khi clone các kho Git bên ngoài không đáng tin cậy, cần sử dụng phiên bản mới nhất và kiểm tra trạng thái bảo mật
  • Cần phát hiện các tên tệp có chứa ký tự bất thường trong kho (đặc biệt là carriage return) và rà soát trước khi clone

1 bình luận

 
GN⁺ 2025-07-09
Ý kiến trên Hacker News
  • Tất cả điều này dẫn đến hiện tượng khi thực hiện clone submodule, lúc đọc thì dùng dạng path = ... nhưng khi ghi lại lại ghi vào một đường dẫn khác không kết thúc bằng ^M

    • Đặt câu hỏi việc "thực thi mã từ xa" mà bài viết nói đến xảy ra ở đây như thế nào, và mức độ nghiêm trọng về mặt bảo mật là đến đâu

    • Dù PoC vẫn chưa được công bố, nội dung này gần như là biến thể trực tiếp của exploit CVE-2024-32002, và các bài test trong commit vá lỗi cũng được nhắc là gợi ý rất lớn

    • Trích phần mô tả CVE-2024-32002: có thể thao túng ác ý một kho chứa có submodule để lợi dụng lỗi của Git, từ đó ghi tệp vào thư mục .git/ thay vì worktree của submodule. Nhờ vậy có thể ghi hook sẽ được chạy ngay trong quá trình clone, khiến người dùng thậm chí không có cơ hội kiểm tra đoạn mã thực sự sẽ được thực thi

    • Tóm lại, có thể đưa git hook độc hại vào kho chứa; thông thường git hook không được cài khi git clone, nhưng đòn tấn công lần này lại có thể khiến điều đó xảy ra, mở ra khả năng hook chạy ngay trong quá trình clone

    • Có thể xem thêm thông tin về CVE mới tại đây

      • Khi đọc giá trị cấu hình, Git loại bỏ ký tự CR và LF, nhưng khi ghi thì không escape CR, dẫn đến việc dữ liệu bị mất khi đọc lại
      • Nếu đường dẫn submodule có chứa ký tự CR ở cuối, Git sẽ dùng đường dẫn đã bị loại bỏ CR đó, khiến submodule có thể bị checkout vào vị trí sai
      • Nếu giữa đường dẫn đã bị lược bỏ đó và thư mục hook của submodule đã tồn tại sẵn một symlink, kẻ tấn công có thể thực thi mã tùy ý thông qua hook post-checkout
      • Ngoài CVE này còn có khá nhiều lỗ hổng Git khác, nên cũng đáng để xem cùng
    • Nhắc đến sự thật đơn giản nhưng khó chịu: nếu có thể ghi tệp tùy ý thì phần lớn trường hợp cuối cùng cũng dẫn tới RCE

  • Nhắc đến rủi ro khi dùng DSL ad-hoc để viết tệp cấu hình

    • Thường không có đặc tả chính thức cho cú pháp, và tiêu chuẩn thực sự của việc phân tích lại nằm rải rác trong các phần hiện thực serialize/deserialize tự viết

    • Nếu hai bên lệch nhau (ví dụ parser đã thêm cú pháp mới nhưng writer không theo kịp), khác biệt khi phân tích cú pháp có thể trở thành quả bom hẹn giờ

    • Bài học là cần có một source of truth duy nhất, và các phần phụ thuộc vào nó nên được tự động sinh ra từ đó

    • Chỉ ra rằng lỗi này lại là chuyện khác với vấn đề source of truth

      • Đây là lỗi logic thuần túy; nếu Unix có một thư viện hệ thống chuẩn kiểu đó thì lỗi tương tự cũng hoàn toàn có thể xảy ra ở đó
      • Nếu nó nằm trong một thư viện chuẩn như vậy thì tác động hẳn còn nghiêm trọng hơn nhiều; hiện tại thiệt hại ít hơn vì chủ yếu giới hạn trong nhóm nhà phát triển
    • DSL dùng ở đây (định dạng tệp ini) tuy là ad-hoc nhưng rất phổ biến, quen thuộc và được tổ chức khá tốt, nên nhìn chung đủ để xem là một đặc tả thực dụng

      • Bản chất lỗi không nằm ở định dạng mà ở parser (hoặc lexer) viết tay chen vào giữa, và có ý kiến cho rằng nên chấm dứt kiểu mã như vậy
      • Vẫn còn một vài chỗ cần parser viết tay thật khéo, nhưng tuyệt đối không nên dùng cho định dạng trao đổi dữ liệu; cần ini thì dùng toml, không thích thì JSON, thậm chí YAML cũng được, muốn tìm thêm đau khổ thì XML, còn nếu nhất quyết đòi định dạng nhị phân thì dùng protobufs
      • Kết luận là nếu không phải tác giả ngôn ngữ lập trình thì đừng tự viết parser, nhất định phải dùng thư viện
  • Đã tự tái hiện lại vấn đề và đưa nó lên kho chứa này

    • Lập tức thử cập nhật Git lên bản mới nhất, nhưng Arch vẫn chưa có

    • Dự định sẽ tránh pull cho đến khi có bản vá mới, vì có thể các kho chứa phổ biến bật tự động pull sẽ gặp sự cố, nên việc nâng cấp có lẽ sẽ mất khá nhiều thời gian

    • Đặt câu hỏi liệu lỗ hổng lần này có bị công khai trước khi vá xong hay không

      • Trước đây, các bài viết giải thích ai có thể khai thác lỗ hổng đến mức nào thường xuất hiện sau khi đã vá vài tháng; còn dạo này thì mong rằng trong mọi bài đăng người ta sẽ nói lướt qua nhưng rõ ràng rằng "cái này thực sự nguy hiểm ngay bây giờ" hay là "đã vá rồi nên không cần lo"
  • Khi thấy câu "chỉ sửa đổi đơn giản từ exploit cũ", có người thắc mắc vì sao Git không dùng Landlock (một tính năng sandbox bảo mật chỉ có trên Linux)

    • Với git clone, cần có cấu trúc chỉ đọc với thư mục config, quyền đọc/ghi với thư mục đích clone, và cấm gọi tiến trình con

    • Châm biếm khoảnh khắc quá quen thuộc là exploit nào cũng cứ bật máy tính ra làm minh họa

    • Có ý kiến rằng nếu cấm gọi tiến trình con thì mọi git hook như post-checkout đều sẽ hỏng

      • Nếu không cần các tính năng đó thì có thể chạy git trong môi trường kiểu container như seccomp, nhưng nhiều chức năng sẽ bị giới hạn
    • Và cũng chỉ ra rằng nếu không có tiến trình con thì sẽ không thể dùng git qua ssh

  • Đặt câu hỏi liệu bản thân Homebrew có phải là vấn đề hay không, tức là nó có dùng recursive clone hay không

    • Tìm thấy khả năng đó trong đoạn mã này

    • Có ý kiến rằng mục tiêu của Homebrew vốn là chạy mã trong kho chứa, nên nếu không có recursive clone thì ngược lại mới thấy lạ

      • Vấn đề là RCE chỉ thực sự có ý nghĩa khi dữ liệu được clone lẽ ra không được thực thi; mà trường hợp như vậy thì hiếm
  • Nhìn câu nói nổi tiếng của Jon Postel về CR+LF mà bồi hồi nhớ lại

    • Chia sẻ bài viết này cùng nhận xét rằng so với năm 2003 thì lời khuyên đó giờ có thể không còn đúng nữa
    • Theo như phần giải thích khi đó của Mark Crispin, mọi người đã hiểu sai, và điều này cũng liên hệ với ví dụ Daniel J. Bernstein từng nêu ra vào cuối thập niên 1990 về các vấn đề phát sinh trong quá trình chuyển đổi người-máy (parsing/quoting)
    • Quan sát rằng đã 25 năm trôi qua mà vấn đề trong mã quoter không escape CR vẫn lặp lại, và ngay cả sau khi sửa thì cũng vẫn chưa kiểm tra toàn bộ whitespace
    • Kết quả git blame cho thấy đoạn mã gây vấn đề được viết từ 19 năm trước, trùng vào thời điểm các hồi tưởng 10 năm của Bernstein
    • Chia sẻ thêm tài liệu như commit liên quan, bài viết về qmail
    • Cuối cùng nhấn mạnh thực tế là những bài học vất vả học được ở thế kỷ 20 vẫn phải học lại trong thế kỷ 21
  • Có vẻ sẽ phải chờ thêm một chút vì Homebrew vẫn chưa có bản cập nhật git 2.50.1

    • Gợi ý thử cập nhật qua issue này hoặc brew install git --HEAD
  • Chia sẻ rằng cả Homebrew lẫn Debian Bookworm vẫn đang cung cấp phiên bản dễ bị tấn công

    • Thông báo rằng giờ Homebrew cũng đã dùng được bản 2.50.1
  • Suy nghĩ xem liệu system call dùng để liệt kê thư mục có nên phủ nhận sự tồn tại của tệp nếu tên tệp chứa các ký tự điều khiển ASCII (bytes), coi đó là lỗi hỏng đĩa, hay nên xử lý theo cách nào khác

    • Cũng nêu khả năng trong locale hiện tại các byte đó lại mang ý nghĩa khác, vì không giống Windows giả định toàn bộ tên tệp là UTF-16, nên có thể phát sinh tình huống bất ngờ

    • Chỉ ra ngắn gọn rằng đây là vấn đề phát sinh vì trên các hệ Unix, tên tệp (và các chuỗi khác) chỉ đơn thuần là mảng byte mà thôi