Nhà nghiên cứu công bố PoC cho lỗ hổng RCE trên GitLab, cho phép thực thi lệnh dưới quyền Git

Nhà nghiên cứu bảo mật Yuhang Wu tại depthfirst đã công bố bản khai thác Proof-of-Concept (PoC) lỗ hổng RCE cho phép thực thi lệnh dưới quyền git trên máy chủ GitLab 18.11.3. Một người dùng đã xác thực có thể kích hoạt lỗ hổng bằng cách commit hai tệp Jupyter notebook đặc biệt mà không cần quyền quản trị hay tương tác của nạn nhân.
GitLab RCE Exploit

Nhà nghiên cứu bảo mật Yuhang Wu tại depthfirst đã công bố bản khai thác Proof-of-Concept (PoC) hoạt động được, cho phép thực thi lệnh dưới quyền git trên máy chủ GitLab tự quản lý (self-managed) phiên bản 18.11.3 chưa được vá lỗi.

Một người dùng thông thường đã xác thực có thể kích hoạt lỗ hổng này bằng cách commit hai tệp Jupyter notebook được tạo đặc biệt và yêu cầu so sánh sự thay đổi (diff) giữa chúng. Chuỗi tấn công này không cần quyền quản trị viên, không cần quyền truy cập CI runner, không cần tương tác của nạn nhân hoặc quyền truy cập vào dự án của người dùng khác.

Bản khai thác công khai này được thiết kế riêng cho GitLab 18.11.3 trên kiến trúc x86-64; tuy nhiên các lỗi Oj tiềm ẩn ảnh hưởng đến nhiều phiên bản hơn. Các phạm vi bị ảnh hưởng bao gồm GitLab Community Edition (CE) và Enterprise Edition (EE) từ 15.2.0 đến 18.10.7, từ 18.11.0 đến 18.11.4, và từ 19.0.0 đến 19.0.1.

Phiên bản khắc phục và lỗ hổng Oj

Các phiên bản đầu tiên được khắc phục là 18.10.8, 18.11.519.0.2. Oj là một bộ phân tích cú pháp JSON hiệu suất cao cho Ruby với mã nguồn C thuần túy đáng kể.

Các gem đã công bố từ phiên bản 3.13.0 đến 3.17.1 đều dính lỗi; 3.17.3 là bản phát hành đầu tiên chứa cả hai bản vá. Các lỗ hổng này ảnh hưởng đến các gói Free, Premium và Ultimate. Bản thân ngôn ngữ Ruby không bị ảnh hưởng.

Việc khai thác thành công sẽ chạy dưới quyền git. Phạm vi ảnh hưởng thực tế tùy thuộc vào mức độ cô lập khi triển khai, nhưng có thể bao gồm mã nguồn, Rails secrets, thông tin xác thực dịch vụ, dữ liệu CI/CD và các dịch vụ nội bộ có thể truy cập từ ứng dụng. GitLab.com đã được vá vào ngày 10 tháng 6.

Khách hàng sử dụng dịch vụ chuyên dụng (Dedicated customers) không cần thực hiện hành động nào. Các nhà vận hành hệ thống tự quản lý nên chuyển sang phiên bản được hỗ trợ có chứa bản vá. Người dùng Helm và Operator cần kiểm tra phiên bản GitLab bên trong image Webservice, không chỉ phiên bản chart hoặc Operator. depthfirst cho biết họ chưa ghi nhận trường hợp khai thác nào trong thực tế tính đến ngày 24 tháng 7.

Cả thông tin từ depthfirst lẫn ghi chú phát hành ngày 10 tháng 6 của GitLab đều không liệt kê mã định danh CVE hoặc điểm số CVSS cho hai lỗi trong chuỗi tấn công. Cả hai cũng không cung cấp biện pháp khắc phục tạm thời mà đều hướng dẫn người dùng nâng cấp hệ thống.

GitLab Exploited Demonstration
Minh họa quá trình khai thác GitLab thành công.

Phân tích kỹ thuật và cơ chế rò rỉ bộ nhớ

Trình kết xuất notebook của GitLab chuyển dữ liệu JSON của tệp .ipynb do kho lưu trữ kiểm soát sang Oj::Parser.usual.parse bên trong một Puma worker có tuổi thọ dài. Điều này đưa dữ liệu notebook do kẻ tấn công kiểm soát vào trạng thái bộ phân tích cú pháp gốc của Oj bên trong tiến trình ứng dụng GitLab.

Phân tích kỹ thuật của depthfirst cho thấy cách một lỗi kiểm soát con trỏ callback, trong khi lỗi còn lại làm rò rỉ địa chỉ heap cần thiết để thu hẹp phạm vi tìm kiếm ASLR (Address Space Layout Randomization).

Oj lưu trữ trạng thái lồng nhau trong một ngăn xếp cố định 1.024 byte nhưng không bao giờ kiểm tra xem độ sâu có vượt quá giới hạn đó hay không. Do đó, các mảng lồng nhau sâu có thể ghi các byte 0x01 vào trạng thái bộ phân tích cú pháp liền kề. Bản khai thác làm hỏng buf.head, khiến Oj chuyển một con trỏ giả mạo cho hàm realloc(). Sau đó, một cấp phát mảng Ruby sẽ thu hồi chính vùng nhớ jemalloc 3.584 byte đó và ghi đè lên p->start.

Oj cấp phát một key đối tượng 65.565 byte, cắt bớt độ dài của nó xuống còn 29 trong một trường 16-bit có dấu, và trả về 29 byte chứa con trỏ cấp phát key đang hoạt động. GitLab đưa con trỏ đó vào bản diff notebook được kết xuất, cung cấp cho bản khai thác khả năng rò rỉ địa chỉ cần thiết để vượt qua ASLR. Trên bản cài đặt GitLab 18.11.3 với hai worker, quá trình tìm kiếm thường mất từ 5 đến 10 phút.

Thực thi lệnh RCE

Hai tệp notebook được sắp xếp theo thứ tự chữ cái trong một yêu cầu diffs_stream sẽ giữ cả hai giai đoạn bên trong cùng một Puma worker, nơi sử dụng lại bộ phân tích Oj toàn cục của tiến trình. Tệp đầu tiên làm hỏng callback và gây ra lỗi mà GitLab sẽ bắt được trước khi tiếp tục xử lý bản diff. Lần phân tích cú pháp tiếp theo sẽ kích hoạt con trỏ đã bị ghi đè và thực thi lệnh system() thông qua một chuỗi gadget đặc thù của bản build.

Bản demo công khai đóng gói chuỗi tấn công trong một phòng thí nghiệm GitLab 18.11.3 x86-64 cục bộ và khiến Puma worker kết nối ngược lại (reverse shell) dưới quyền git.

depthfirst đã báo cáo các lỗi Oj vào ngày 21 tháng 5 và người duy trì đã hợp nhất các bản vá vào ngày 27 tháng 5. Oj 3.17.3 được phát hành vào ngày 4 tháng 6. Các nhà nghiên cứu đã báo cáo chuỗi tấn công GitLab vào ngày 5 tháng 6; GitLab đã xác nhận vào ngày 8 tháng 6.