
Trong tháng 3/2026, Kaspersky đã phát hiện các tin tặc chèn mã độc vào thư viện Python để phát triển LiteLLM, vốn đóng vai trò là cổng đa chức năng cho một tập hợp nhiều các tác nhân AI. Những kẻ tấn công phát tán hai phiên bản LiteLLM độc hại và lây nhiễm trên các hệ thống cmục tiêu. Đáng lưu ý, cả hai phiên bản này đều được đưa vào kho lưu trữ PyPI của Python.
Phân tích kỹ thuật của Kaspersky cho thấy mục tiêu chính của tin tặc là các máy chủ lưu trữ dữ liệu bí mật liên quan đến AWS, Kubernetes, NPM,… và các cơ sở dữ liệu khác như MySQL, PostgreSQL, MongoDB,... Ngoài ra, phần mềm độc hại bao gồm chức năng đánh cắp dữ liệu từ ví tiền điện tử và các kỹ thuật để duy trì trong cụm Kubernetes.
Phân tích kỹ thuật
Vụ xâm phạm đã ảnh hưởng đến kênh phân phối gói phần mềm thông qua PyPI. Ngày 24/3/2026, hai phiên bản LiteLLM độc hại là litellm==1.82.7 và litellm==1.82.8 đã được tải lên kho lưu trữ. Cụ thể, trong phiên bản 1.82.7 mã độc được nhúng vào tệp proxy_server.py và trong phiên bản 1.82.8, tệp litellm_init.pth đã được thêm vào.
Cả hai phiên bản của thư viện đều chứa cùng một mã độc nhưng cách thực thi lại khác nhau. Với phiên bản 1.82.7, mã độc chỉ hành động khi người dùng gọi đến hàm proxy, trong khi ở phiên bản 1.82.8, một tệp .pth được nhúng vào và cho phép thực thi phần mềm độc hại mỗi khi interpreter khởi động.
Mã độc trong các tệp proxy_server.py và litellm_init.pth chứa đoạn code viết bằng Python và mã hóa bằng Base64. Sau khi thực thi, tập lệnh bị nhiễm sẽ lưu code này cùng với chính nó dưới dạng tệp p.py và ngay lập tức mã độc được khởi chạy.
Tập lệnh p.py khởi chạy phần mềm độc hại chính - một tập lệnh khác cũng được mã hóa bằng Base64 mà không lưu vào ổ đĩa. Đồng thời, nó ghi đầu ra của phần mềm này vào một tệp trong thư mục mà từ đó nó được khởi chạy. Trước khi được ghi, đầu ra được mã hóa bằng thuật toán AES-256-CBC với một khóa ngẫu nhiên được tạo và lưu vào tệp session.key. Tệp khóa cũng mã hóa bằng cách sử dụng khóa RSA công khai đã được khởi tạo trước. Khóa mã hóa và đầu ra được kết hợp vào một tệp tpcp.tar.gz và gửi đến máy chủ từ xa của kẻ tấn công.
Sau khi khởi chạy, một quá trình quét đệ quy các thư mục trên hệ thống của nạn nhân như /root, /app/, /var/www,… bắt đầu. Trong mỗi thư mục tập lệnh sẽ quét nội dung của các tệp và trích xuất chúng ra bộ đệm stdout. Tiếp theo, tập lệnh thu thập thông tin hệ thống, sau đó tiến hành tìm kiếm dữ liệu nhạy cảm. Các dữ liệu nằm trên máy chủ và trong cơ sở hạ tầng của các dịch vụ khác nhau được nhắm đến bao gồm: khóa SSH; tài khoản GIT; các tệp .env; cấu hình AWS, Kubernetes, dịch vụ email, cơ sở dữ liệu và WireGuard; các tệp liên quan đến Helm, Terraform và CI; khóa và chứng chỉ TLS.
Một đặc điểm đáng chú ý của phần mềm độc hại này là nó không chỉ giới hạn ở việc đánh cắp các tệp tin và cấu hình từ ổ đĩa mà còn cố gắng trích xuất các dữ liệu nhạy cảm từ cơ sở hạ tầng đám mây. Mã độc sử dụng các địa chỉ 169[.]254[.]169[.]254 và 169[.]254[.]170[.]2. Địa chỉ đầu tiên tương ứng với IMDS, thông qua đó một phiên bản EC2 (gồm một máy chủ ảo trong AWS, một máy đang chạy trên đám mây) có thể truy xuất metadata và thông tin xác thực vai trò IAM tạm thời (một tài khoản AWS với một tập hợp các quyền mà một dịch vụ hoặc ứng dụng có thể sử dụng để lấy thông tin xác thực tạm thời cho các cuộc gọi đến API AWS).
Trong khi đó, địa chỉ thứ hai được sử dụng trong Amazon ECS để cấp thông tin xác thực tạm thời cho một container trong quá trình thực thi. Do đó, tập lệnh độc hại không chỉ nhắm mục tiêu vào các dữ liệu tĩnh mà còn cả những dữ liệu do đám mây cung cấp, có thể cấp quyền truy cập trực tiếp vào các tài nguyên AWS tại thời điểm lây nhiễm.
Ngoài ra, mã độc còn tìm kiếm cấu hình ví tiền điện tử, cũng như các webhook liên kết với các ứng dụng nhắn tin Slack và Discord. Điều này cho thấy những kẻ tấn công không chỉ quan tâm đến các bí mật và tài khoản cơ sở hạ tầng, mà còn cả các kênh liên lạc trong nhóm phát triển.
Ở giai đoạn tiếp theo, mã độc sẽ chuyển từ thu thập dữ liệu sang duy trì chỗ đứng trong cơ sở hạ tầng cụm Kubernetes: nếu có đủ quyền truy cập, nó sẽ cấu hình một pod đặc quyền (đơn vị thực thi nhỏ nhất trong Kubernetes, chứa một hoặc nhiều container) bằng cách bật tùy chọn securityContext.privileged=true và gắn kết hệ thống tệp gốc của nút thông qua hostPath.
Điều này cho phép mã độc thoát khỏi container và thực hiện các hành động ở cấp độ nút. Tiếp theo, nó thực hiện một giai đoạn lây nhiễm khác: lưu một tập lệnh mã hóa Base64, đồng thời ngụy trang thành một thành phần hệ thống hợp pháp vào ổ đĩa của nút Kubernetes tại đường dẫn /root/.config/sysmon/sysmon.py và đăng ký nó thông qua systemd. Sau khi khởi chạy, tập lệnh chờ một khoảng thời gian trễ ban đầu là 300 giây, sau đó bắt đầu liên lạc định kỳ với nút C2 checkmarx[.]zone/raw, lấy liên kết đến payload tiếp theo từ đó.
Nếu giá trị nhận được khác với trạng thái đã lưu trước đó trong /tmp/.pg_state, tập lệnh sẽ tải xuống một tệp mới vào /tmp/pglog, cấp quyền thực thi cho tệp đó và chạy ngầm. Ở giai đoạn này, kẻ tấn công giành được quyền kiểm soát hệ thống và có khả năng thường xuyên cập nhật các payload mà không cần phải nhúng lại. Vì payload độc hại không được ghi vào thư mục tệp tạm thời của container mà ghi trực tiếp vào nút cụm Kubernetes, nên kẻ tấn công vẫn có quyền truy cập vào cơ sở hạ tầng ngay cả sau khi container đã bị chấm dứt.
Một kịch bản tương tự được sử dụng cho việc duy trì cục bộ: trong trường hợp không có Kubernetes, tập lệnh sysmon.py được triển khai trong thư mục của người dùng tại ~/.config/sysmon/sysmon.py và cũng được đăng ký như một dịch vụ thông qua systemd.
Phiên bản OpenVSX của phần mềm độc hại
Trong quá trình phân tích các tệp tin giao tiếp với máy chủ điều khiển và ra lệnh (C2), các nhà nghiên cứu phát hiện các phiên bản độc hại của hai tiện ích mở rộng của phần mềm Checkmarx phổ biến: ast-results 2.53.0 và cx-dev-assist 1.7.0. Phiên bản này được tải xuống từ checkmarx[.]zone/static/checkmarx-util-1.0.4.tgz bằng cách sử dụng các tiện ích cài đặt gói NodeJS và được đặt tên là checkmarx-util. Điểm khác biệt chính so với phiên bản Python là nó không cố gắng nâng cao đặc quyền lên cấp độ nút Kubernetes và không tạo pod có đặc quyền để duy trì. Thay vào đó, phiên bản NodeJS thực hiện duy trì cục bộ trong môi trường hiện tại. Điều này có nghĩa là biến thể NodeJS chỉ tồn tại ở nơi nó đang chạy.
Ngoài ra, danh sách các thư mục cần tìm kiếm và đánh cắp thông tin bí mật trong phiên bản này hạn chế hơn đáng kể so với Python. Các tiện ích mở rộng Checkmarx được sử dụng để quét mã và cấu hình cơ sở hạ tầng, vì vậy kẻ tấn công không chỉ có quyền truy cập vào các tệp project mà còn vào một phần đáng kể môi trường phát triển, token và cấu hình cục bộ.
Trong quá trình đánh giá tác động của cuộc tấn công, các nhà nghiên cứu nhận thấy các nạn nhân xuất hiện ở nhiều khu vực trên thế giới. Hầu hết các vụ tấn công lây nhiễm xảy ra ở Nga, Trung Quốc, Brazil, Hà Lan và UAE.
Như phân tích kỹ thuật cho thấy, các đoạn mã độc được tìm thấy trong các phiên bản LiteLLM không chỉ nguy hiểm vì chúng đánh cắp các tệp tin chứa dữ liệu nhạy cảm, mà còn vì chúng nhắm mục tiêu đồng thời vào nhiều thành phần cơ sở hạ tầng quan trọng: hệ thống cục bộ, dữ liệu thời gian chạy trên đám mây, cụm Kubernetes và thậm chí cả các khóa mã hóa. Phạm vi thu thập dữ liệu rộng lớn như vậy cho phép kẻ tấn công nhanh chóng chuyển từ việc xâm phạm một hệ thống và môi trường Python duy nhất sang chiếm đoạt tài khoản dịch vụ, bí mật và toàn bộ cơ sở hạ tầng.
Phòng ngừa và bảo vệ
Để phòng ngừa các mối đe dọa này, Kaspersky khuyến cáo người dùng nên sử dụng giải pháp chuyên dụng để giám sát các thành phần mã nguồn mở.
Hiện nay, các phiên bản LiteLLM bị xâm phạm đã được gỡ bỏ khỏi PyPI và OpenVSX. Nếu người dùng đã sử dụng chúng thì nên thực hiện các biện pháp sau trên hệ thống và cơ sở hạ tầng của mình:
- Thực hiện quét toàn bộ hệ thống bằng một giải pháp bảo mật đáng tin cậy.
- Xoay vòng tất cả các thông tin xác thực có khả năng bị xâm phạm: khóa API, biến môi trường, khóa SSH, token tài khoản dịch vụ Kubernetes và các secret khác.
- Kiểm tra các máy chủ và cụm máy chủ để tìm dấu hiệu bị xâm nhập: sự hiện diện của các tệp ~/.config/sysmon/sysmon.py và các pod đáng ngờ trong Kubernetes.
- Xóa bộ nhớ cache và lập danh sách các mô-đun PyPI: kiểm tra xem có mô-đun độc hại nào không và khôi phục về các phiên bản sạch.
- Kiểm tra các dấu hiệu cho thấy hệ thống đã bị xâm nhập (các tệp trên hệ thống hoặc dấu hiệu trên mạng).
