Khai thác lỗ hổng CodeRabbit: từ một PR đơn giản đến RCE và quyền ghi trên 1 triệu repo
(research.kudelskisecurity.com)- Nhóm nghiên cứu bảo mật đã thành công thực thi mã từ xa (RCE) trên máy chủ production của CodeRabbit và làm rò rỉ token API cùng thông tin bí mật
- Thông qua một PR sử dụng Rubocop, họ đã đánh cắp biến môi trường, đồng thời có thể truy cập PostgreSQL và đọc/ghi 1 triệu repository
- Việc rò rỉ private key của GitHub App khiến kẻ tấn công có thể tiêm mã độc vào kho lưu trữ quy mô lớn, bao gồm cả repo public và private, sửa mã nguồn và gây ra thiệt hại thực tế
- Phía CodeRabbit đã phản ứng ngay trong vòng vài giờ sau khi nhận báo cáo lỗ hổng và tăng cường các biện pháp bảo mật
- Khi chạy công cụ bên ngoài, cần nhấn mạnh sự cần thiết của ngăn chặn sự cố bảo mật bằng cách cô lập sandbox, áp dụng đặc quyền tối thiểu và chặn mạng
Giới thiệu
- Tháng 1 năm 2025, nhóm nghiên cứu Kudelski Security đã công bố một lỗ hổng bảo mật nghiêm trọng trong CodeRabbit
- Trên CodeRabbit, một công cụ tự động hóa review PR được sử dụng rộng rãi, đã xác nhận các vấn đề nghiêm trọng gồm remote code execution (RCE), rò rỉ biến môi trường và thông tin nhạy cảm, cùng khả năng giành quyền Read/Write với hơn 1 triệu repository
- Bài viết này phân tích chi tiết nội dung lỗ hổng đã được công bố tại Black Hat USA và có giá trị tham khảo cao như một trường hợp thực tế về lỗ hổng trong công cụ review dạng code và các hệ thống tích hợp liên quan
- Lỗ hổng được báo cáo đã được vá nhanh chóng ngay sau khi thông báo
Tổng quan về CodeRabbit
- CodeRabbit là ứng dụng review code dựa trên AI được cài đặt nhiều nhất trên GitHub/GitLab Marketplace
- Ứng dụng này đã review 1 triệu repository và 5 triệu pull request trên hai nền tảng lớn
- Mỗi khi người dùng tạo hoặc cập nhật PR, engine AI sẽ phân tích mã và tự động tạo comment cùng đề xuất
- Các tính năng như tóm tắt code, phát hiện lỗ hổng bảo mật, gợi ý cải tiến và tạo sơ đồ mang lại hiệu quả lớn trong việc nâng cao năng suất phát triển
Cách sử dụng và cấu trúc quyền của CodeRabbit
- Gói Pro cung cấp tính năng tích hợp linter và công cụ SAST (phân tích tĩnh)
- Khi xác thực tài khoản GitHub và cài đặt app, người dùng sẽ cấp quyền đọc/ghi cho các repository đã chọn
- Nếu cơ chế quản lý quyền này bị lạm dụng, nó có thể tạo ra tác động trực tiếp đến mã nguồn của mọi repo đã cài đặt
Thực thi công cụ bên ngoài và phát hiện khai thác
- Khi phát hiện thay đổi mã trong PR, CodeRabbit sẽ tự động chạy nhiều công cụ phân tích tĩnh bên ngoài (ví dụ: Rubocop)
- Rubocop được thiết kế để có thể dùng file cấu hình
.rubocop.ymlnhằm nạp file mở rộng Ruby bên ngoài (ext.rbv.v.)- Kẻ tấn công chèn mã độc vào
.rubocop.ymlvàext.rb, sau đó gửi PR để khiến CodeRabbit thực thi mã đó trên máy chủ từ xa
- Kẻ tấn công chèn mã độc vào
- Mã được thực thi bằng kỹ thuật này đã gửi toàn bộ biến môi trường của máy chủ về máy chủ của kẻ tấn công
Phân tích nội dung rò rỉ biến môi trường
- Các biến môi trường bị rò rỉ bao gồm API key, token và mật khẩu của nhiều dịch vụ khác nhau như:
- API key của Anthropic/OpenAI, encryption salt/password, private key của GitHub App, thông tin kết nối PostgreSQL, v.v.
- Thông qua RCE, có thể gây ra thiệt hại thứ cấp lớn với mức độ ảnh hưởng cao như truy cập cơ sở dữ liệu, thay đổi mã và làm lộ thông tin nội bộ của dịch vụ
- Nhóm nghiên cứu có thể tiếp tục thăm dò sâu hơn trên máy chủ thực, nhưng đã dừng lại sau khi chỉ xác minh ở mức tối thiểu để tránh ảnh hưởng đến vận hành dịch vụ
Giành quyền Read/Write trên 1 triệu repository
- Có thể xác thực với GitHub API bằng GITHUB_APP_PEM_FILE (private key) có trong biến môi trường
- Đối với mọi kho lưu trữ mà CodeRabbit có thể truy cập (bao gồm public và private):
- Có thể thực hiện các quyền rất mạnh như đọc/ghi mã nguồn, thay thế file phát hành (tấn công chuỗi cung ứng), thay đổi lịch sử git, v.v.
- Mã tái hiện (PoC) đã được công bố, chứng minh khả năng bị khai thác trên thực tế
Tóm tắt PoC
- Sử dụng các thư viện như PyGitHub cùng private key và App ID bị rò rỉ để phát hành access token cho repository tùy ý
- Với token này, có thể tự động hóa việc clone repository private, thay đổi file, tạo commit mới và sửa đổi file phát hành
Khả năng xâm phạm repository nội bộ/riêng tư của CodeRabbit
- Do chính tổ chức CodeRabbit cũng cài đặt và sử dụng dịch vụ của họ, nên cũng có thể truy cập và sao chép repo mã nguồn nội bộ của CodeRabbit
- Chỉ cần biết tên tổ chức là có thể tra installation ID rồi ngay lập tức truy cập danh sách repo tương ứng
Tóm tắt tác động
- Truy cập trái phép vào repository private và rò rỉ dữ liệu cá nhân
- Nguy cơ tấn công chuỗi cung ứng như chỉnh sửa mã nguồn, chèn mã độc/backdoor
- Khả năng liên kết khai thác với các lỗ hổng bổ sung như GitHub Actions
- RCE trực tiếp có thể dẫn tới phá hủy dữ liệu, làm gián đoạn dịch vụ và gây thiệt hại dây chuyền sang các dịch vụ khác
Bối cảnh và giới hạn trong phán đoán của AI
- Ngay cả trong quá trình tấn công, PR vẫn được CodeRabbit review bình thường, và dù có để lại comment cảnh báo lỗ hổng nhưng thực tế không nhận diện được cú pháp đe dọa
- Điều này cho thấy công cụ review code AI không thực sự hiểu được bối cảnh của tình huống rủi ro ngoài đời thực
Ứng phó và khuyến nghị
- CodeRabbit đã vô hiệu hóa Rubocop, thay thế thông tin bí mật và kiểm toán hệ thống chỉ trong vài giờ sau khi nhận báo cáo lỗ hổng
- Sự cố phát sinh từ công cụ không áp dụng sandbox (Rubocop), và sau khi khắc phục, hệ thống đã được cải tiến để chạy mọi công cụ bên ngoài trong môi trường cô lập
- Để tăng cường bảo mật, cần nhấn mạnh sự cần thiết của thiết kế phòng thủ như tối thiểu hóa biến môi trường trong môi trường chạy công cụ bên ngoài, giới hạn IP truy cập mạng và chặn truy cập Internet
Công bố có trách nhiệm và kết luận
- Vào tháng 1 năm 2025, sau khi được báo cáo, phản ứng và biện pháp khắc phục đã được triển khai nhanh chóng
- Dù chỉ dừng ở PoC, trường hợp này cho thấy nếu là kẻ tấn công độc hại thì rất dễ lạm dụng để chọn lọc repo giá trị cao, triển khai ransomware quy mô lớn hoặc thực hiện các cuộc tấn công chuỗi cung ứng mang tính phá hoại
- Tầm quan trọng của việc triển khai sandbox và nguyên tắc đặc quyền tối thiểu một lần nữa được khẳng định khi tích hợp với các công cụ phân tích bên ngoài và dịch vụ tự động hóa dựa trên AI
1 bình luận
Ý kiến trên Hacker News
Ôi trời, đây đúng là một lỗ hổng cực kỳ nghiêm trọng. May mà lần này đã được vá, nhưng ngay từ đầu việc một vấn đề như thế này tồn tại đã là vấn đề rồi. Quy tắc cơ bản nhất khi xây dựng hệ thống phân tích mã người dùng trên nền tảng đám mây là trình phân tích bắt buộc phải chạy trong môi trường cô lập. Việc chèn mã trực tiếp có thể xảy ra thông qua plugin, còn linter/trình phân tích/trình biên dịch là những phần mềm phức tạp với bề mặt tấn công rộng. Không bao giờ nên giả định rằng chạy các công cụ như vậy trên kho lưu trữ tùy ý trong môi trường dùng chung là an toàn. Tôi cũng từng vận hành một nền tảng phân tích mã, và ngay cả khi chạy trình phân tích do chính chúng tôi phát triển trên kho của khách hàng, chúng tôi cũng thiết kế để nó hoạt động trong môi trường sandbox. Không cấp quyền biến môi trường hay yêu cầu mạng, nhưng dù vậy việc phân tích vẫn chỉ chạy trong sandbox. Đó là cách duy nhất để làm phân tích mã một cách an toàn
https://github.com/getgrit/gritql
Tôi đã hủy gói trả phí của Coderabbit. Việc một công ty chỉ chịu thừa nhận vấn đề sau khi nó lan truyền đủ mạnh trên HN luôn là điều khiến tôi lo ngại. Trên blog chính thức không thấy nhắc gì đến lỗ hổng lần này, và hôm nay cũng không có bài mới. Tôi nghĩ ai cũng có thể mắc sai lầm, nhưng việc không công khai minh bạch khi chuyện như vậy xảy ra sẽ làm tổn hại hình ảnh doanh nghiệp
Chi tiết “trong lúc exploit đang chạy, CodeRabbit lại trực tiếp để lại bình luận cảnh báo nguy hiểm trên chính PR đó, trong khi thực tế lại đang bị hack do chạy PR ấy” thật quá kỳ lạ. Cảm giác sống trong một thế giới nơi AI đang nói rằng chính nó đang bị hack nghe rất siêu thực. Ngoài ra, dù đội CodeRabbit phản ứng rất nhanh, điều đáng lo hơn là “các nhà cung cấp khác hoàn toàn không trả lời liên hệ điều tra và vẫn còn dễ tổn thương”. Xin hoan nghênh đội CodeRabbit, nhưng tất cả mọi người đều nên cực kỳ cẩn trọng
Trong một phần phát biểu chính thức của CEO có câu “vấn đề xảy ra vì Rubocop chạy ngoài môi trường sandbox”, nhưng thành thật mà nói tôi hơi nghi ngờ. Tại sao chỉ riêng một thành phần lại hoạt động hoàn toàn khác biệt, mà lại đúng là tác vụ bị khai thác?
Đây thực sự là một bài viết rất thú vị, nhưng thật ra cũng không có gì đáng ngạc nhiên. Người dùng cứ vô tư cài thêm hàng loạt ứng dụng có quyền quá rộng, còn hệ thống quyền của github cũng có vấn đề nên chuyện này gần như là điều tất yếu. Rất nhiều người cấp quyền ghi kho lưu trữ cho github app, thậm chí cả quyền đám mây, một cách lạm dụng. Dù có bảo vệ nhánh, pull request vẫn có thể mở ra quyền truy cập đặc quyền qua github actions. Để cấu hình cho đúng thì phải chỉnh github oidc audience, mà tài liệu lại không rõ ràng. Ngay cả khi yêu cầu nhà phát triển ứng dụng giảm bớt quyền và tạo bản riêng với một số chức năng bị tắt, đa số họ cũng không quan tâm và không hiểu vấn đề bảo mật. github cần cho phép phân nhỏ quyền truy cập của app hơn nữa, và nhìn chung quyền hạn cũng cần được chi tiết hóa hơn
Thật sự quá sốc. Tôi còn chưa đọc hết bài mà đã choáng váng vì có quá nhiều thứ. Đoạn nói hacker có thể cài malware vào các file phân phối của công cụ/thư viện/phần mềm mã nguồn mở ở quy mô từ 100 nghìn đến 1 triệu khiến tôi nghĩ thế giới suýt nữa có thể đã sụp đổ. Thật khó tưởng tượng còn bao nhiêu vấn đề tương tự đang tồn tại phía trước
Tôi nghĩ những thất bại bảo mật nghiêm trọng như thế này nên được phân loại là “xâm phạm” hoặc “sự cố”, và bắt buộc phải công khai thông qua truyền thông. Một công cụ có thể truy cập hơn 7.000 khách hàng và 1 triệu kho lưu trữ lại bị đột nhập bằng một exploit đơn giản đến mức có lẽ một đứa trẻ 11 tuổi cũng viết được. Nếu việc hack dễ đến vậy thì khả năng bot, blackhat, APT... đã xâm nhập và âm thầm bám trụ từ trước là rất cao. Nếu họ đã ở trong đó trước khi whitehat công bố, thì việc vá lỗ hổng chỉ ngăn kẻ tấn công mới, chứ chưa chắc loại bỏ được những kẻ đã lẻn vào sẵn. Tôi biết bảo mật rất khó, nhưng thật sự phải tỉnh táo lại
Một trong các vấn đề là nhiều trình phân tích mã, bundler, trình biên dịch (ví dụ như trình biên dịch Rust) có thể chạy mã tùy ý mà không hề cảnh báo. Ví dụ, hacker gửi cho tôi một kho lưu trữ dưới danh nghĩa bài tập tuyển dụng, và nếu tôi chạy “npm install” hoặc lệnh biên dịch Rust thì máy tính của tôi có thể rơi vào tay hacker ngay lập tức. Hoặc nếu một máy tính của đồng nghiệp trong công ty bị hack và mã độc lọt vào kho lưu trữ, thì cuối cùng cả một tập đoàn toàn cầu cũng có thể bị các hacker nước ngoài chiếm quyền. Cấu trúc này là do npm và trình biên dịch Rust tạo ra. Những công cụ như vậy cần yêu cầu xác nhận rõ ràng mỗi khi thực thi lệnh bên ngoài (dĩ nhiên có thể cache danh sách lệnh cho phép để khỏi hỏi lại). Linux cũng nên cung cấp sandbox an toàn mà lập trình viên có thể dùng dễ dàng, thay vì ai cũng phải tự dựng lấy. Hơn nữa, có những tác vụ như cài gói JS mà trong một số trường hợp không cần phải chạy mã bên ngoài. Và việc đưa bí mật cùng cấu hình vào biến môi trường là một cách làm thực sự tệ. Có vẻ người tạo ra “12-factor app” không biết rằng còn có cờ dòng lệnh và file cấu hình
rustc(bản thân trình biên dịch)pslà có thể thấy hết mọi thông tinViệc khóa quyền (private key) có thể “trở thành github app theo ý muốn” lại được lưu trong biến môi trường là một thực hành tệ hại đến mức khó chấp nhận. Ai cũng có thể bị hack, nhưng đây là điều cơ bản nhất trong quản lý bí mật. Trong tài liệu chính thức của github cũng ghi rất rõ là không nên đặt private key vào biến môi trường. Đây thật sự là kiến thức nền tảng
https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/managing-private-keys-for-github-apps#storing-private-keys
Ngay khi đọc đến đoạn nói file cấu hình Rubocop có thể chỉ định đường dẫn tới file Ruby mở rộng, tôi đã nghĩ “chẳng lẽ họ chạy thẳng công cụ mở rộng do người dùng cung cấp trong môi trường production sao...”, và đúng là như vậy thật. Tất nhiên, chỉ chặn một lỗ như thế cũng không có nghĩa là đã thực sự an toàn. Phần lớn linter chắc hiếm khi được audit hay fuzzing với đầu vào mang tính tấn công; chuyện này chẳng khác nào để cửa mở toang rồi bật biển đèn neon “xin mời hack!”