TL; DR
Một cụm năm gói npm, được đăng tải trên hai tài khoản khác nhau, đã gửi một postinstall Đoạn mã này đọc thông tin đăng nhập đám mây từ máy chủ và gửi chúng ra khỏi thiết bị. Các gói tin mang tên ma và tên miền lậu — coral-wraith, ecto-corsair-whisper-6f3b9, ecto-corsair-flag-x9m4, ecto-rust-read-f3a9c1, ecto-nightly-spirit — và mã hóa bất cứ thứ gì họ thu thập được thành một chuỗi giả mạo. ecto_module: Tệp kê khai YAML được gửi đi trước khi chúng tôi theo dõi cụm máy chủ. tế bào chất.
Phần mềm độc hại chỉ được thực thi khi phát hiện một môi trường cụ thể: một máy chủ có tên là... Chuỗi thập lục phân 12 ký tự và một thư mục làm việc bên dưới /app/node_modules — hình dạng của một bản dựng container hóa hoặc trình xử lý CI. Khi cổng đó được vượt qua, hook sẽ truy vấn Dịch vụ siêu dữ liệu phiên bản AWS (IMDSv2) Đối với thông tin xác thực vai trò IAM, liệt kê Quản lý bí mật AWS trên ba khu vực, trích xuất các biến môi trường, đọc các tệp tin dưới /appvà tìm kiếm các chuỗi "capture-the-flag" (chiếm cờ). Sau đó, nó trích xuất kết quả theo hai cách: một tín hiệu đến một... webhook.site bộ thu thập và một yêu cầu PUT khai báo đến điểm cuối IP thô, với danh sách các phương án dự phòng ưu tiên localhost.
Các mô tả gói phần mềm sau này ghi là "Phần mềm CTF dùng để kiểm tra chuỗi cung ứng verdaccio". Chúng tôi báo cáo mô tả này như một sự thật có thể quan sát được. Bản thân hành vi – truy cập trực tiếp ra địa chỉ IP công cộng, đọc thông tin xác thực IMDS thực tế, gọi Secrets Manager thực tế – vẫn là như vậy bất kể nhãn mác, và đó là lý do tại sao các phiên bản này được phân loại là độc hại.
Một cái tên trong nhóm đó, coral-wraithKhông chỉ dừng lại ở một lần phát hành. Nó được tái bản liên tiếp hàng chục phiên bản chỉ trong vài giờ — 1.0.0 leo lên 6.0.0 — và một phiên bản trước đó cùng tên đã sử dụng từ "inflated" (lạm phát). 9999.0.x số phiên bản, hình dạng cổ điển của một nỗ lực nhầm lẫn phụ thuộcTrải qua quá trình xử lý đó, tải trọng được phát huy rõ rệt: từ một tín hiệu liệt kê máy chủ đơn lẻ thành một hệ thống chuyển hướng thông tin xác thực AWS hoàn chỉnh được bao bọc bởi các bước kiểm tra môi trường giúp nó hoạt động âm thầm bên ngoài mục tiêu dự định.
| Gói | 5 cái tên; coral-wraith một mình nó đã được tái bản trên hàng chục phiên bản khác nhau. |
| Hệ sinh thái | NPM |
| Cài đặt vector | postinstall kịch bản vòng đời |
| Mục tiêu chính | Thông tin xác thực vai trò AWS IAM + Giá trị bí mật của Secrets Manager, biến môi trường, /app các tập tin |
| trục xuất | webhook.site tín hiệu + địa chỉ IP thô C2 PUT |
| Cổng kích hoạt | Tên máy chủ 12 chữ số thập lục phân + /app/node_modules cwd, cộng thêm một bước kiểm tra môi trường nhằm ngăn chặn việc thực thi payload bên ngoài ngữ cảnh đó. |
| Mức độ nghiêm trọng | cao — tiết lộ thông tin xác thực đám mây và bí mật được quản lý từ Môi trường xây dựng và chạy được đóng gói trong container |
Giải phẫu tấn công
Mọi gói trong cụm đều được xây dựng theo cùng một cách: gần như trống rỗng. chỉ mục.js (module.exports = {}), một dòng package.json kịch bản - “postinstall”: “node postinstall.js” — và tải trọng trong postinstall.jsViệc cài đặt gói là đủ để chạy hook; không cần nhập khẩu hay gọi hàm nào khác.
Cổng nhắm mục tiêu. Trước khi thực hiện bất cứ điều gì, thiết bị mang tải trọng thuộc họ ecto sẽ kiểm tra môi trường xung quanh:
function isAppWorker(): host = os.hostname() if host does NOT match /^[0-9a-f]{12}$/ -> exit if cwd does NOT contain "/app/node_modules" -> exit if cwd contains "/tmp/npm-safe" -> exit otherwise -> proceed Tên máy chủ 12 chữ số thập lục phân là hình dạng mặc định mà Docker gán cho một container, và /app/node_modules là đường dẫn cài đặt thông thường trong container. Điều khoản thứ ba sẽ dừng lại nếu đường dẫn trông giống như thư mục giải nén được bảo vệ bằng hộp cát. Kết quả là, tải trọng vẫn ở trạng thái ngủ đông trên máy tính xách tay của nhà phát triển hoặc hộp cát phân tích và chỉ được kích hoạt bên trong quá trình xây dựng hoặc chạy trong container — loại môi trường có nhiều khả năng chứa thông tin đăng nhập đám mây đang hoạt động. Gói sớm nhất trong cụm, ma san hô, không có cổng như vậy và thực hiện quá trình thu thập (đơn giản hơn) của nó một cách vô điều kiện.
Bộ sưu tậpKhi cánh cổng đi qua, móc sẽ bung ra. execFileSync(“/bin/sh”, [“-c”, …]) và thực thi một lệnh phức hợp duy nhất theo thứ tự sau:
1. PUT /latest/api/token to 169.254.169.254 (IMDSv2 token request) 2. GET .../iam/security-credentials/ (IAM role name) 3. GET .../iam/security-credentials/<role> (temporary credentials) 4. dump env | sort (environment variables) 5. list /app (excl. node_modules) + cat first 15 (application files) 6. aws secretsmanager list-secrets (us-east-1, eu-west-1, eu-central-1) 7. scrape readable files for HTB{...} (capture-the-flag strings) Các bước 1-3 là quy trình truy xuất IMDSv2 điển hình: yêu cầu mã thông báo phiên, sau đó đính kèm nó làm X-aws-ec2-metadata-token Tiêu đề dùng để lấy vai trò IAM của phiên bản và các khóa truy cập tạm thời của vai trò đó. Việc lựa chọn triển khai IMDSv2 thay vì IMDSv1 đơn giản hơn, không cần xác thực. GET Điều đáng chú ý là, điều này có nghĩa là tải trọng hoạt động ngay cả trên các phiên bản được cấu hình để yêu cầu truy cập siêu dữ liệu dựa trên mã thông báo, đây là biện pháp tăng cường bảo mật được AWS khuyến nghị. Thông tin xác thực được trả về ở bước 3 có thời hạn ngắn. ID khóa truy cập/Bí MậtTruy CậpChìa Khóa/Mã thông báo Các bộ ba được giới hạn phạm vi theo vai trò của phiên bản; bất cứ điều gì vai trò đó có thể làm, người nắm giữ các khóa đó cũng có thể làm trong suốt thời gian hiệu lực của thông tin xác thực.
Các bước 4–6 mở rộng phạm vi quay. env Lệnh `dump` ghi lại mọi thứ mà quá trình xây dựng hoặc chạy kế thừa — trên thực tế, đây thường là nơi lưu trữ các mã thông báo đăng ký, chuỗi kết nối cơ sở dữ liệu và khóa API. / app File Walk đọc tối đa mười lăm tập tin ứng dụng từ bên ngoài. nút_mô-đun, có thể tạo ra cấu hình bề mặt, .NS các tập tin, hoặc nguồn. Bước 6 gọi aws secretsmanager list-secrets ở ba khu vực; thông tin xác thực được lấy ở các bước 1-3 chính xác là những gì xác thực các cuộc gọi đó, vì vậy việc đọc IMDS và chuỗi liệt kê của Trình quản lý bí mật kết hợp với nhau thành một quá trình leo thang duy nhất: vai trò phiên bản → kho bí mật được quản lý. Bước 7 là một sự ám chỉ đến khung bắt cờ — khi một HTB{…} Nếu cờ được tìm thấy, nó sẽ được gửi riêng, nếu không, dữ liệu thô thu thập được sẽ được chia thành bốn phần và gửi đi.
Các phiên bản sau này trong cụm máy chủ còn tiến xa hơn trong việc leo thang vấn đề. Thay vì dừng lại ở việc kiểm kê, chúng phân tích phản hồi IMDS, xuất các khóa tạm thời dưới dạng... AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN các biến môi trường, xác nhận danh tính với aws sts nhận dạng người gọivà sau đó lặp lại mọi bí mật được trả về bởi danh sách bí mật gọi aws secretsmanager get-secret-value trên mỗi tệp — truy xuất nội dung bí mật, chứ không chỉ tên của chúng. Các phiên bản tương tự cũng đọc các tệp nhị phân cờ thay thế quy trình (/readflag và bạn bè) và cố gắng sạc chạy chống lại bất kỳ dự án Rust nào được tìm thấy bên dưới / app, mở rộng phạm vi thu hoạch vượt ra ngoài thông tin xác thực đám mây sang bất cứ thứ gì mà môi trường xây dựng cung cấp.
Các phiên bản sau này cũng tự giới hạn quyền truy cập một cách quyết liệt hơn. Ngoài tên máy chủ 12 chữ số thập lục phân và /app/node_modules Khi thực hiện các bước kiểm tra, payload sẽ kiểm tra cấu hình kho gói đang hoạt động và đường dẫn thư mục làm việc, và sẽ thoát một cách im lặng khi chúng cho thấy ngữ cảnh phân tích hoặc sao chép chứ không phải mục tiêu thực sự. Hiệu ứng tổng thể là một payload không thực hiện bất kỳ hành động nào có thể quan sát được trong hầu hết các môi trường kiểm tra và chỉ chạy toàn bộ quá trình thu thập thông tin khi nó tự đánh giá mình đang ở trên một máy chủ container hóa thực sự.
LọcDữ liệu thu thập được sẽ rời khỏi máy chủ thông qua hai kênh. Đầu tiên là tín hiệu định vị (beacon). POST tới mức cố định webhook.site Bộ thu thập dữ liệu mang theo tên máy chủ, UID số, thư mục làm việc và tối đa 120 KB dữ liệu đã thu thập. Thứ hai, dữ liệu được đóng gói vào một "tệp kê khai mô-đun" YAML giả và PUT đến /api/modules/ trên máy chủ mục tiêu:
ecto_module: name: "<flag-or-chunk-0>" version: "1.0.0" power_level: "<chunk-1>" ship_deck: "<chunk-2>" cargo_hold: "<chunk-3>" Tên trường kê khai (mức năng lượng, boong tàu, khoang chứa hàng) chỉ là phần trang trí — dữ liệu bị đánh cắp nằm bên trong các giá trị chuỗi, đó là lý do tại sao trình giám sát mạng lại thấy thứ trông giống như một quá trình tải lên bản kê khai đăng ký gói lành tính hơn là một vụ rò rỉ dữ liệu rõ ràng. Kênh tín hiệu mang nhiều hơn thế: POST cơ thể để webhook.site Bao gồm tên máy chủ, UID số, thư mục làm việc và tối đa 120 KB dữ liệu đã thu thập, vì vậy chỉ cần một tín hiệu thành công duy nhất cũng có thể truyền tải toàn bộ dữ liệu. webhook.site Đây là một dịch vụ kiểm tra yêu cầu miễn phí; việc sử dụng nó như một bộ thu thập có nghĩa là nhà điều hành không bao giờ phải thiết lập cơ sở hạ tầng tiếp nhận riêng cho kênh đó, và các yêu cầu đã ghi lại sẽ được lưu trữ trong kho của dịch vụ.
Bản kê khai PUT duyệt qua một danh sách dự phòng bắt đầu bằng một vài 127.0.0.1/localhost các cổng và sau đó chuyển tiếp đến ba địa chỉ công cộng trong `154.57.164.0/24` Phạm vi, dừng lại ở điểm cuối đầu tiên trả lời với trạng thái 2xx. Thứ tự ưu tiên localhost phù hợp với mô tả "thử nghiệm verdaccio" (một registry cục bộ trên loopback), nhưng các phương án dự phòng IP công cộng có nghĩa là dữ liệu sẽ rời khỏi máy chủ bất cứ khi nào loopback không hoạt động — tức là trên bất kỳ máy nào không phải là dàn máy thử nghiệm của tác giả.
Lịch Trình Sự Kiện
Cụm này thể hiện sự tăng trưởng năng lực dần dần chứ không phải là sự sụt giảm đột ngột. Chúng tôi sắp xếp nó theo hành vi quan sát được, chứ không phải theo thời gian thực hiện công bố:
| Traineeship | Gói/Phiên bản | Hành vi |
|---|---|---|
| Chạy sớm | coral-wraith 9999.0.x | Số phiên bản được thổi phồng phù hợp với nỗ lực gây nhầm lẫn về phụ thuộc; liệt kê và trích xuất dữ liệu trong quá trình cài đặt. |
| Hạt | coral-wraith 1.0.0 | postinstall thu thập các tệp id/env/flag; một lần PUT duy nhất đến 154[.]57[.]164[.]71:30782, dấu hiệu ECT-472839 |
| Lặp lại nhanh chóng | coral-wraith 1.0.1 → 6.0.0 | Hàng chục bản phát hành trong vài giờ; tải trọng được tăng cường. isAppWorker() cổng, lấy thông tin xác thực IMDSv2, đầy đủ get-secret-value trục xoay, kiểm tra môi trường đăng ký/đường dẫn và các dấu hiệu đánh dấu đích kép |
| Tên song song | ecto-corsair-whisper-6f3b9 1.0.14–1.0.18 | Cùng một tải trọng được kiểm soát; webhook.site danh sách dự phòng beacon và đa điểm cuối |
| Biến thể | ecto-rust-read-f3a9c1 1.0.1–1.0.2 | Thêm các dấu hiệu đánh dấu bồn rửa bổ sung ECT-987654, ECT-654321, ECT-839201 |
| Biến thể | ecto-corsair-flag-x9m4 1.0.0, ecto-nightly-spirit 1.1.0 | Cùng một loại tải trọng được kiểm soát, cùng một trung tâm điều khiển và thiết bị phát tín hiệu. |
Đặc điểm nổi bật của cụm này là nhịp độ phát hành: thay vì một gói và một phiên bản duy nhất, cùng một tên được phát hành lại nhiều lần với tốc độ nhanh, mỗi lần phát hành chỉ là một biến thể nhỏ so với lần trước, cùng với một số gói khác tên nhưng mang cùng nội dung. Trong phạm vi đó... thì thầm Mã nguồn của nhóm này được chia thành hai dấu vân tay gần giống nhau — một nhóm kích hoạt hai phát hiện quan trọng, nhóm còn lại kích hoạt ba (một điểm đọc tệp bổ sung) — nhưng cả hai đều dẫn đến cùng một tải trọng; sự khác biệt là do sự thay đổi mã, chứ không phải là sự phân nhánh hành vi. Các phiên bản của thì thầm Các trường hợp nằm ngoài phạm vi phân tích (ít nhất là đến phiên bản 1.0.25 tại thời điểm viết bài) đã được quan sát trực tiếp trên hệ thống đăng ký, và ma san hô Tên gọi tiếp tục leo lên nấc thang phiên bản riêng của nó qua cùng một cửa sổ.
Các chỉ số thỏa hiệp
Tất cả các chỉ báo bên dưới đều được trích xuất từ mã nguồn gói phần mềm trên ổ đĩa. Các chỉ báo mạng đã được lược bỏ chức năng này.
mạng
| chỉ số | Vai trò |
|---|---|
hxxp://154[.]57[.]164[.]71:30782 | Mục tiêu C2 PUT (coral-wraith) |
hxxp://154[.]57[.]164[.]80:30543 | C2 PUT dự phòng (ecto-*) |
hxxp://154[.]57[.]164[.]82:31250 | C2 PUT dự phòng (ecto-*) |
hxxp://154[.]57[.]164[.]71:31289 | C2 PUT dự phòng (ecto-*) |
hxxps://webhook[.]site/602a4c72-7033-4e28-92ea-dc66e59206e5 | Bộ thu tín hiệu |
169[.]254[.]169[.]254/latest/... | Đọc thông tin xác thực IMDSv2 (phía đích, siêu dữ liệu AWS) |
Hành vi/tệp
| chỉ số | Vai trò |
|---|---|
"postinstall": "node postinstall.js" | Cài đặt vector |
ecto_module: YAML với power_level / ship_deck / cargo_hold phím | lược đồ kê khai xuất khẩu |
Dấu hiệu bồn rửa ECT-472839, ECT-987654, ECT-654321, ECT-839201 | Đoạn đường C2 /api/modules/<marker> |
isAppWorker() cổng: máy chủ /^[0-9a-f]{12}$/, cwd chứa /app/node_modules | Điều kiện kích hoạt |
aws secretsmanager list-secrets kết thúc us-east-1, eu-west-1, eu-central-1 | Liệt kê bí mật |
HTB{...} thu thập biểu thức chính quy | Thu hoạch cờ vua |
Mã băm của tệp (sha256, được ghi lại tại thời điểm phân tích)
| Tập tin | sha256 |
|---|---|
coral-wraith/postinstall.js | ce5ff035cfdfed1d0015446424b352c27b66bcb77e9fdb0a51e4245199146824 |
ecto-corsair-whisper-6f3b9 1.0.18/postinstall.js | b58432acba376aa6976f0490d9a1c04257ccdbc856d8390260c50322d63e31c3 |
Sự quy kết và hành vi quan sát được
Năm tên gói này được công bố dưới hai tài khoản npm khác nhau, nhưng chúng có chung đủ cơ sở hạ tầng để được coi là một cụm duy nhất: cùng một cụm. ecto_module lược đồ manifest, giống nhau ECT-472839 dấu hiệu đánh dấu điểm chìm chính, giống nhau webhook.site ID bộ thu thập và các điểm cuối C2 trong cùng một Khối `154.57.164.0/24`. Gói hạt giống (`coral-wraith`)(đơn giản hơn và không bị kiểm soát) và do đó, các ecto-family bị kiểm soát được xem như những sự lặp lại trên một bộ công cụ chứ không phải là những nỗ lực độc lập.
Các gói phần mềm tự mô tả mình, trong các phiên bản sau này, như sau: “Tải trọng CTF cho việc kiểm thử chuỗi cung ứng Verdaccio.” Chúng tôi nêu nhãn đó như một sự thật có thể quan sát được và không diễn đạt lại nó như một phát hiện về mục đích. Những gì mã thực hiện là rõ ràng và độc lập với cách nó được dán nhãn: nó đọc thông tin xác thực vai trò IAM từ dịch vụ siêu dữ liệu phiên bản, liệt kê các bí mật được quản lý trên ba vùng AWS và truyền kết quả đến một địa chỉ IP công cộng và một bộ thu thập webhook của bên thứ ba. Một bộ kiểm thử chỉ sử dụng vòng lặp ngược thực sự sẽ không cần danh sách dự phòng IP công cộng, việc đọc thông tin xác thực IMDS hoặc các cuộc gọi Trình quản lý bí mật xuyên vùng. Bởi vì việc truyền dữ liệu ra ngoài và phạm vi thông tin xác thực là có thật, các phiên bản bị giới hạn đã được phân loại là độc hại.
Cơ chế chỉ cho phép truy cập qua container là đặc điểm đáng chú ý nhất về mặt vận hành. Nó vừa là biện pháp né tránh – giữ im lặng trên máy tính xách tay và trong môi trường phân tích – vừa là biện pháp nhắm mục tiêu, chỉ kích hoạt khi có nhiều khả năng tồn tại vai trò IAM thực và các bí mật đang hoạt động. Các nhà phân tích chạy các gói này trong môi trường phân tích thông thường sẽ không thấy gì; hành vi này chỉ biểu hiện khi sử dụng tên máy chủ kiểu Docker và đường dẫn cài đặt trong container.
Tác động, xu hướng và hướng dẫn dành cho người phòng thủ
Lỗ hổng ở đây là việc tiết lộ thông tin xác thực và bí mật trên đám mây bên trong các container xây dựng và chạy. Thông tin xác thực vai trò IAM được lấy từ IMDS mang theo tất cả các quyền mà vai trò đó nắm giữ; secretsmanager:ListSecrets (và bất kỳ phần tiếp theo nào) Nhận giá trị bí mật(Điều này mở rộng phạm vi sang cả các bí mật ứng dụng được lưu trữ. Việc sao lưu biến môi trường thường chứa các mã thông báo đăng ký, URL cơ sở dữ liệu và khóa API. Trong ngữ cảnh CI hoặc container — chính xác là những gì cổng kiểm tra lựa chọn — chỉ cần một lần cài đặt gián tiếp của một trong những gói này cũng đủ để làm rò rỉ những thông tin đó.)
Ectoplasm phù hợp với một mô hình mà chúng ta vẫn thường thấy: các phần mềm độc hại được cài đặt nhằm truy cập vào siêu dữ liệu đám mây và các bí mật được quản lý thay vì các tệp cục bộ, và tự giới hạn để chỉ kích hoạt trong các môi trường có giá trị cao. Sau đây là hai nhận xét về phòng thủ.
- Hình dạng có thể nhận biết đượcMột hook cài đặt npm/PyPI có đồ thị gọi hàm truy cập cả API bí mật đám mây (trình quản lý bí mật AWS, bí mật gcloud, az keyvault) hoặc địa chỉ IMDS và một sink thoát mạng là một mô hình hẹp, có tín hiệu cao — nó hầu như không bao giờ xuất hiện trong một kịch bản vòng đời hợp lệ. Phân tích dòng chảy tĩnh Có thể gắn cờ mà không cần phụ thuộc vào bất kỳ tên miền hoặc địa chỉ IP cụ thể nào.
- Việc thích nghi với môi trường khắc nghiệt sẽ làm giảm tác động của nó. Việc thực thi IMDSv2 với giới hạn số bước nhảy là 1 ngăn chặn khối lượng công việc của vùng chứa truy cập vào siêu dữ liệu của phiên bản; việc giới hạn phạm vi vai trò IAM ở mức đặc quyền tối thiểu sẽ hạn chế phạm vi ảnh hưởng của bất kỳ thông tin xác thực nào bị rò rỉ; và việc chạy các cài đặt với –Ignore-scripts Trong CI, nó loại bỏ hoàn toàn vectơ install-hook đối với các gói không cần đến nó.
Đối với người bảo vệ, các bước kiểm tra thực tế là: cảnh báo về các kết nối đi ra từ các container xây dựng/CI đến các địa chỉ IP công cộng không được phép trong quá trình hoạt động. NPM cài đặt; theo dõi các truy cập IMDS bắt nguồn từ các tập lệnh vòng đời gói; và coi bất kỳ hook cài đặt nào gọi đến CLI đám mây là đáng ngờ cho đến khi được chứng minh ngược lại.
Hai lưu ý bổ sung cụ thể cho cụm này. Thứ nhất, vì việc kích hoạt được giới hạn trong môi trường container, một gói có vẻ không hoạt động khi được kiểm tra trên máy trạm vẫn có thể đang hoạt động trong môi trường sản xuất — việc kiểm tra cần phải tái tạo tên máy chủ container và các điều kiện đường dẫn, hoặc đọc trực tiếp mã nguồn, thay vì chỉ dựa vào câu nói “Tôi đã cài đặt nó và không có gì xảy ra”. Thứ hai, việc sử dụng dịch vụ kiểm tra yêu cầu công khai làm bộ thu tín hiệu có nghĩa là một số dữ liệu bị rò rỉ có thể được khôi phục để ứng phó sự cố: một tổ chức tìm thấy một trong những gói này trong cây phụ thuộc của mình có thể suy luận về những gì một tín hiệu thành công sẽ chứa từ logic thu thập của tải trọng, và nên xoay vòng bất kỳ thông tin xác thực vai trò IAM, mã thông báo đăng ký và bí mật được quản lý nào có thể truy cập được từ môi trường xây dựng hoặc thời gian chạy bị ảnh hưởng. Luân chuyển chứng chỉViệc cài đặt lại, chứ không phải gỡ bỏ gói phần mềm, mới là biện pháp khắc phục hiệu quả sau khi quá trình cài đặt đã hoàn tất.





