Skip to main content

Command Palette

Search for a command to run...

ForceMemo - Chiến dịch Supply Chain Attack nhắm vào hàng trăm repo Python trên GitHub

Published
5 min read
ForceMemo - Chiến dịch Supply Chain Attack nhắm vào hàng trăm repo Python trên GitHub

Tổng quan

Phát hiện chiến dịch tấn công nguy hiểm và tinh vi mang tên là ForceMemo , kẻ tấn công xâm chiếm hàng trăm tài khoản GitHub và tiêm mã độc giống hệt nhau vào hàng trăm repository Python. Các lần tiêm mã sớm nhất được ghi nhận từ ngày 8/3/2026, và chiến dịch vẫn còn đang hoạt động với các repo mới tiếp tục bị xâm phạm.

Cuộc tấn công nhắm vào các dự án Python bao gồm Django apps, ML research code, Streamlit dashboards, và PyPI packages bằng cách chèn mã bị obfuscate vào các file như setup.py, main.py, và app.py. Bất kỳ ai chạy pip install từ repo bị xâm phạm hoặc clone và thực thi code đó đều sẽ kích hoạt malware.

Dưới đây là bằng chứng điển hình: file setup.py của repo amirasaran/django-restful-admin (70 stars) bị chèn mã độc obfuscated ở cuối file hợp lệ.


Cơ chế tấn công 4 giai đoạn

Giai đoạn 1: Chiếm tài khoản qua GlassWorm

Cơ chế chiếm tài khoản đã được xác định: các developer bị xâm phạm đã nhiễm malware GlassWorm thông qua các extension VS Code và Cursor độc hại. Payload stage 3 của GlassWorm bao gồm một module đánh cắp credential chuyên dụng, thu thập GitHub token từ nhiều nguồn: git credential fill, VS Code extension storage, ~/.git-credentials, và biến môi trường GITHUB_TOKEN.

Bằng chứng cho thấy xâm phạm ở cấp độ tài khoản rất rõ ràng: khi một tài khoản có nhiều repository bị chiếm, toàn bộ repo dưới tài khoản đó đều bị tiêm mã. Ví dụ, user BierOne có 6 repo bị xâm phạm, tổ chức wecode-bootcamp-korea bị 6 repo, và HydroRoll-Team bị 6 repo.

Ảnh dưới đây minh họa GitHub code search cho thấy toàn bộ repo của tài khoản BierOne đều chứa malware giống hệt nhau bằng chứng điển hình của xâm phạm ở cấp tài khoản:


Giai đoạn 2: Tiêm mã lén lút qua Force-Push

Thay vì mở pull request hoặc tạo commit mới (cả hai đều hiển thị trong activity feed của repo), kẻ tấn công thực hiện 3 bước: lấy commit hợp lệ mới nhất trên default branch, rebase lại với malware được chèn vào một file Python chủ chốt, rồi force-push lên default branch. Message commit và author date đều được giữ nguyên từ commit gốc — chỉ có committer date mới lộ ra dấu hiệu giả mạo.


Giai đoạn 3: C2 trên Solana Blockchain

Đây là điểm kỹ thuật đặc biệt nhất của chiến dịch. Thay vì kết nối tới một C2 server truyền thống có thể bị takedown, malware đọc lệnh từ blockchain Solana. Nó truy vấn một địa chỉ Solana cụ thể để lấy transaction memo chứa dữ liệu JSON với payload URL. Địa chỉ C2 là BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC.

Malware thử đến 9 Solana RPC endpoint khác nhau làm fallback, khiến nó cực kỳ khó bị chặn khi chỉ block một endpoint đơn lẻ. Việc dùng blockchain làm kênh C2 có nghĩa là kẻ tấn công có thể cập nhật payload URL bất cứ lúc nào bằng cách đăng một transaction mới — và không ai có thể xóa hoặc kiểm duyệt các lệnh đó khi đã lên chain.

Một transaction ngày 25/2/2026 còn lộ ra cấu hình C2 trực tiếp — gồm C2 server trên port 5000, endpoint fingerprint IP nạn nhân, và DHT node trên port 10000 làm fallback peer-to-peer.


Giai đoạn 4: Thực thi payload

Sau khi malware lấy được payload URL từ Solana memo, nó tải Node.js v22.9.0 từ nodejs.org về home directory của người dùng (hỗ trợ đa nền tảng Windows/macOS/Linux, x64/ARM), tải payload JavaScript đã mã hóa, ghi file i.js để giải mã và thực thi payload qua Node.js đã tải, rồi tạo persistence file ~/init.json với timer 2 ngày để tránh thực thi lặp lại.


Tìm kiếm repo bị ảnh hưởng

Toàn bộ danh sách repo bị ảnh hưởng có thể tìm thấy bằng cách tìm kiếm biến marker của malware trên GitHub: lzcdrtfxyqiplpd.

https://github.com/search?q=lzcdrtfxyqiplpd&type=code

Cách kiểm tra nếu bị ảnh hưởng

Nếu bạn cài Python package trực tiếp từ GitHub hoặc clone và chạy repo Python, hãy kiểm tra bằng lệnh grep -r "lzcdrtfxyqiplpd" . để tìm marker variable, kiểm tra sự tồn tại của ~/init.json, kiểm tra Node.js đã tải về với ls ~/node-v22*, kiểm tra file i.js trong các project directory, và xem lại git commit history tìm các commit có committer date mới hơn đáng kể so với author date.


IOCs

Indicator

Value

Solana C2 address

BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC

Solana funding wallet

G2YxRa6wt1qePMwfJzdXZG62ej4qaTC7YURzuh2Lwd3t

Marker variable

lzcdrtfxyqiplpd

XOR key

134

Committer email

"null" (string)

Node.js version

v22.9.0

Persistence file

~/init.json

JS payload file

i.js

Code comments lang

Russian

CIS exclusion

Bỏ qua thực thi nếu hệ thống dùng locale/timezone Nga

C2 server IPs

45.32.151.157, 45.32.150.97, 217.69.11.57, 217.69.11.99, 217.69.0.159, 45.76.44.240

Tham khảo

GlassWorm Attack Uses Stolen GitHub Tokens to Force-Push Malware Into Python Repos

ForceMemo: Hundreds of GitHub Python Repos Compromised via Account Takeover and Force-Push

More from this blog

F

FPT IS Security

726 posts

Dedicated to providing insightful articles on cybersecurity threat intelligence, aimed at empowering individuals and organizations to navigate the digital landscape safely.