LiteLLM 1.107.0 bị cài mã độc, nhắm vào khóa API AI

Công cụ cổng mô hình lớn LiteLLM bị tấn công đầu độc chuỗi cung ứng vào ngày 21/10. Theo công ty bảo mật đám mây Wiz, phiên bản bị can thiệp LiteLLM 1.107.0 đã được đưa lên PyPI trong ngày hôm đó, còn các image trên GHCR và Docker Hub gắn thẻ v1.107.0, latest, main-latest, main-stable cũng bị cài cùng một bộ chương trình đánh cắp. Phiên bản an toàn gần nhất do nhà phát triển công bố là v1.106.2.

LiteLLM do BerriAI phát triển. Cách dùng phổ biến là dựng một lớp proxy trong nội bộ doanh nghiệp, chuyển tiếp qua giao diện thống nhất tới hàng trăm dịch vụ mô hình như OpenAI, Anthropic, Bedrock. Phía sau proxy lưu khóa API của từng nhà cung cấp, và đó chính là điểm mà cuộc tấn công này nhắm tới.

Cài xong là bắt đầu đánh cắp

Gói độc hại đặt ba tệp vào thư mục gốc site-packages: cook.pth, cook.py và sitecustomize.py. Hai tệp đầu tận dụng cơ chế .pth của Python, chỉ cần trình thông dịch khởi động là chạy, không cần mã nghiệp vụ phải import LiteLLM.

Chương trình đánh cắp có tên nội bộ là privcollect, gồm 16 mô-đun, nhắm tới các mục tiêu sau:

  • Thông tin đăng nhập và cookie trình duyệt của Chrome, Firefox, Edge, Safari
  • Thông tin xác thực đám mây của AWS, GCP, Azure
  • Khóa API của các hãng AI như OpenAI, Anthropic, Cohere
  • Khóa riêng SSH, GPG và lịch sử shell
  • Thông tin xác thực của các nhà cung cấp thượng nguồn, truy vấn trực tiếp từ cơ sở dữ liệu PostgreSQL của LiteLLM Proxy

Dữ liệu trước hết được mã hóa bằng AES-256-CBC, khóa lại được bọc thêm một lớp RSA-4096, rồi gửi bằng HTTP POST tới tên miền giả mạo do kẻ tấn công đăng ký là www.litellm[.]dev. Tệp sitecustomize.py chỉ chạy trên Linux và macOS, sẽ tới một kho lưu trữ kiểu "hộp thư chết" trên GitHub để lấy địa chỉ giai đoạn hai; Wiz cho biết ngoài giá trị thử nghiệm, tệp này chưa từng được điền nội dung, và GitHub đã xóa kho đó.

Dàn trải dòng thời gian

Dựa trên mốc giờ UTC do Wiz công bố, có thể ước tính sơ bộ từng khoảng thời gian như sau:

KhâuThời gian (UTC)Kéo dài
Kho giả mạo nhận 10 commit08:56–10:46khoảng 1 giờ 50 phút
Phiên bản độc hại trực tuyến trên PyPI11:39–13:20khoảng 1 giờ 41 phút
Thẻ Docker bị can thiệp còn trực tuyếngỡ xuống vào khoảng 13:53khoảng 2 giờ 14 phút tính từ lúc lên PyPI
Kẻ tấn công kiểm tra thông tin xác thực AWS16:20–17:01cách lúc dữ liệu bị gửi đi khoảng 4,5 giờ

Hơn một giờ trên PyPI nghe có vẻ không dài, nhưng các thẻ như latest sẽ được vô số pipeline CI và hệ thống triển khai Kubernetes tự động kéo về, nên mức độ phơi nhiễm chủ yếu phụ thuộc vào số môi trường đã dựng lại image trong khoảng thời gian này. Wiz không công bố số lượt tải, và số tổ chức bị ảnh hưởng hiện cũng chưa thể xác minh.

Sau khi có được thông tin xác thực, kẻ tấn công dùng vai trò phiên bản AWS trên các CI runner và node Kubernetes bị xâm nhập để gọi các API như sts:GetCallerIdentity, bedrock:ListFoundationModels. Wiz cho rằng cách làm này khớp với thủ đoạn LLMjacking, tức là chiếm dụng tài khoản đám mây của người khác để dùng chùa các lượt gọi mô hình lớn; ở một số môi trường, kẻ tấn công còn liệt kê IAM để do thám thông thường.

Nghi ngờ lối vào là token GitHub

10 commit mà kẻ tấn công đẩy lên nằm trong kho giả mạo Berri-AI/litellm; 9 commit đầu có chữ ký GitHub, commit cuối không có chữ ký và email cũng bị đổi. Phía BerriAI cho biết:

"malicious actions were taken through three engineers' GitHub accounts"
(Các hành động độc hại được thực hiện thông qua tài khoản GitHub của ba kỹ sư.)

LiteLLM nghi ngờ các token OAuth của GitHub CLI này bị lộ từ một bản triển khai nội bộ đang mở ra mạng công cộng, có thể liên quan đến một lỗ hổng vừa được vá; Wiz nêu rõ điểm này chưa được xác nhận. BerriAI cho biết các token liên quan đã bị thu hồi toàn bộ. Những nhóm từng dùng 1.107.0 hoặc đã kéo các image nói trên trong khoảng thời gian đó cần xoay vòng toàn bộ thông tin xác thực đám mây, khóa mô hình và khóa riêng SSH mà máy có thể đọc được.

Nguồn tham khảo: CocoLoop, blog nghiên cứu của Wiz, thông báo của Trung tâm tình báo mối đe dọa Wiz, tuyên bố công khai của BerriAI; đã đối chiếu các phiên bản và thẻ image bị ảnh hưởng, tên tệp độc hại và mốc giờ UTC của từng khâu.