Pakej npm Red Hat Cloud Services Dijangkiti Serangan Pencemaran Rantaian Pemasok

iconMetaEra
Kongsi
Share IconShare IconShare IconShare IconShare IconShare IconCopy
AI summary iconRingkasan

expand icon
Sebuah kebocoran keselamatan telah dilaporkan dalam beberapa paket npm di bawah organisasi Red Hat Cloud Services, menurut berita di rantai dari MetaEra. Sistem MistEye mengesan 96 versi jahat di seluruh 32 paket, dengan tiga dianalisis secara terperinci. Kod jahat dalam paket seperti @redhat-cloud-services/frontend-components-config@6.11.3 dijalankan semasa pemasangan melalui hook preinstall. Malware, varian Shai-Hulud, termasuk pencurian kredensial dan eksploitasi CI/CD. Penyerang menggunakan peralihan ROT/Caesar, AES-GCM, dan enkripsi B5 untuk menyembunyikan beban, yang merebak melalui npm dan alur kerja GitHub.

Latar belakang

Baru-baru ini, sistem pemantauan keselamatan MistEye menangkap maklumat mengenai pelbagai pakej npm di bawah organisasi Red Hat Cloud Services yang menunjukkan versi tidak normal. Peristiwa ini melibatkan 32 pakej npm dan 96 versi di bawah organisasi tersebut. Artikel ini memilih 3 sampel tempatan untuk dianalisis secara dalam dan luar talian: sampel-sampel ini bukan pakej peniru ruang nama atau typo-squatting, tetapi versi pakej sebenar yang menggunakan scope @redhat-cloud-services; daripada kod sumber sampel, dapat disahkan bahawa tarball tersebut mengandungi loader jahat berlapis yang secara automatik dipicu semasa peringkat pemasangan.

Setelah dipulihkan sepenuhnya, dapat dikonfirmasi: beban utama ketiga sampel ini memiliki kemampuan sumber kod untuk membaca memori GitHub Actions Runner, mengumpulkan kredensial multi-cloud dan tempatan, menghantar data ke API GitHub dan dead-drop, menyuntik workflow GitHub, menyebar secara automatik melalui npm, mempertahankan diri melalui Claude Code / VS Code / systemd / LaunchAgent, mengatasi Hardened-Runner / StepSecurity, serta mengesan EDR dan produk keselamatan. Dari segi cakupan kemampuan, objek yang berpotensi terjejas termasuk host pembangun, CI/CD Runner, kontena pembinaan, repositori GitHub, workflow GitHub Actions, saluran penerbitan npm, dan kredensial persekitaran awan; lingkungan sebenar yang terjejas perlu dikonfirmasi dengan menganalisis log pemasangan, audit repositori, dan telemetri dari platform.

Dari segi struktur kod, laluan penyebaran, dan kombinasi kemampuan, perisian jahat ini merupakan varian Shai-Hulud.

MistEye respons

MistEye ialah sistem intelijen ancaman Web3 dan pemantauan keselamatan dinamik yang dikembangkan secara dalaman oleh SlowMist, yang menggabungkan kemampuan pemantauan keselamatan dan pengumpulan intelijen untuk memberikan amaran risiko serta perlindungan aset secara masa nyata kepada pengguna.

Setelah menangkap insiden keracunan rantai pasokan paket npm Red Hat Cloud Services dan sampel jahat yang berkaitan, sistem MistEye telah memicu amaran berisiko tinggi, melakukan analisis sistemik terhadap struktur kekeliruan, dekripsi beban, pemulihan kemampuan, dan IOC serangan tersebut.

(https://enterprise.misteye.io/threat-intelligence/SM-2026-378450)

Ringkasan rantai serangan

Bahagian analisis teknikal dalam artikel ini hanya berdasarkan analisis statik luar talian tempatan, dengan membongkar, menghuraikan dan mengesahkan tiga sampel npm tgz.

Sampel yang dicakup dalam pengesahan ini adalah:

@redhat-cloud-services/frontend-components-config

Versi: 6.11.3

tgz SHA-256:0c9c67ec40d5f23efa1ec3470d0ac88b4993ccc0e92be913fc29a337dfc4f060

@redhat-cloud-services/types

Versi: 3.6.1

tgz SHA-256: d543bb3cdf1569c2b3d38c8a4081ed746cfe78bf3236c2302704d79ab7fa9558

@redhat-cloud-services/rule-components

Versi: 4.7.2

tgz SHA-256: aaf00d06baa3c679b82452c50014e9824b8874e9ca2d150f19095f8de19ba90f

Tiga sampel mempunyai titik serangan yang sama: package.json semuanya mengandungi scripts.preinstall = "node index.js". Ini bermakna sekiranya host pengembang atau persekitaran CI/CD memasang versi-versi ini, fail index.js di direktori utama akan dieksekusi secara automatik semasa peringkat pemasangan, tanpa perlu pengguna mengimport atau menjalankan kod perniagaan secara eksplisit.

Tiga sampel berkongsi beban jahat inti yang sama, tetapi parameter pembungkusan luar berbeza. Dengan kata lain, ketiga-tiga sampel menggunakan nilai pergeseran ROT/Caesar dan key/AES-GCM iv/tag yang berbeza; ini menjadikan ciri statik berdasarkan hash pembungkusan luar, key tetap, atau pergeseran tetap sukar untuk digunakan semula secara langsung antara pembungkusan. Namun, penggerak persekitaran Bun yang telah didekripsi dan hash beban jahat inti adalah serupa: satu ialah modul bantuan pelancaran yang digunakan untuk menyediakan persekitaran Bun, dan yang lain ialah beban inti yang benar-benar mengandungi fungsi jahat. Artikel ini masing-masing menyebut keduanya sebagai "Penggerak Persekitaran Bun (nama pemboleh ubah sumber: _b)" dan "Beban Jahat Inti (nama pemboleh ubah sumber: _p)".

Rantai serangan yang dipulihkan adalah seperti berikut:

Analisis teknikal

1. Masuk: Pencurian skrip npm lifecycle

Ketiga-tiga sampel memicu rantai serangan melalui hook lifecycle preinstall dalam package.json:

"skrip": {

"preinstall": "node index.js"

}

preinstall akan dijalankan secara automatik semasa peringkat pemasangan npm. Bagi komponen frontend biasa, definisi jenis, atau pakej komponen peraturan, biasanya tidak perlu menjalankan fail JavaScript berskala besar di direktori utama semasa pemasangan; ini adalah isyarat pengecualian yang paling langsung.

Bukti peringkat sampel adalah seperti berikut:

@redhat-cloud-services/frontend-components-config@6.11.3

  • utama:lib/index.js
  • medan files: ["/lib", "/bin"]
  • Fail indeks.js direktori utama SHA-256: 545a1838c66e1771f58d84a17b3e1841e5eeab91a73f4ccc59c9492450a6d9c0

@redhat-cloud-services/types@3.6.1

  • utama:index.d.ts
  • Bidang files: Tidak ditetapkan
  • Fail indeks.js direktori utama SHA-256: b86c5ae9e95bd841a595440faa3eb6317441e746f241ae8fd641ab59ed1d1966

@redhat-cloud-services/rule-components@4.7.2

  • utama:index.js
  • Bidang files: Tidak ditetapkan
  • Fail index.js direktori utama SHA-256: 1a30a9abe20bab121aaa75ed040565af14e6cdfb745609ee0e7b94a2d814fb9c

Dalam hal ini, bidang files pada frontend-components-config@6.11.3 hanya menyatakan "/lib" dan "/bin", tetapi terdapat index.js tambahan di direktori utama tarball yang dipanggil oleh preinstall. Penyimpangan ini hanya berlaku untuk sampel ini; types@3.6.1 dan rule-components@4.7.2 tidak menetapkan bidang files, oleh itu penyimpangan ini tidak digeneralisasi kepada semua sampel.

2. Tahap pertama: Array nombor + penggantian huruf ROT/Caesar

Tiga fail index.js pada direktori root ialah fail JavaScript satu baris yang sangat besar, dengan struktur yang seragam, dengan badan utama berupa pembungkus try { eval(...) } catch (...) :

Pembungkus ini terlebih dahulu mengembalikan array nombor besar menjadi rentetan melalui String.fromCharCode, kemudian melakukan pergeseran ROT/Caesar pada huruf abjad Inggeris dalam rentetan tersebut, dan akhirnya menghantar hasil dekod ke dalam eval untuk dilaksanakan. Penanganan pengecualian hanya memaparkan imbuhan wrapper: untuk mengurangkan paparan pengecualian yang ketara semasa kegagalan pemasangan.

Nilai perpindahan luaran dan hash Tahap 2 bagi tiga sampel adalah seperti berikut:

frontend-components-config@6.11.3

index.js saiz: 4,294,798 bait

ROT/Caesar shift: 10

Tahap 2 SHA-256: b19c2fd48535c8c40aeb3e627ce92775f33ef9292611767bb1236c238e6f90cc

types@3.6.1

index.js saiz: 4,135,588 bait

ROT/Caesar shift: 4

Tahap 2 SHA-256:9c0425aa6e6d7792ac38d24f3e7245f42fcaa553ddfeb6bd97677017f10c3b75

rule-components@4.7.2

index.js saiz: 4,294,336 bait

ROT/Caesar shift: 11

Tahap 2 SHA-256: d590bd375d95e4ac072b7ebc1fc4489bcaf5f20a939e92486267aa398bcf1e5d

3. Tahap Kedua: Mendedahkan Bun Bootloader dan Beban Utama dengan AES-128-GCM

Kod Tahap 2 selepas dekripsi ROT/Caesar menjalankan dekripsi AES-128-GCM (Advanced Encryption Standard - Galois/Counter Mode) menggunakan Node.js crypto.createDecipheriv dan menetapkan tag autentikasi melalui setAuthTag. Objek dekripsi adalah dua komponen seterusnya—pemboot Bun dan beban jahat utama.

Di antaranya, penggerak persekitaran Bun bertanggungjawab untuk mengesan, melokasikan, atau mempersiapkan persekitaran Bun supaya kod seterusnya boleh dijalankan melalui Bun; manakala beban jahat utama merupakan komponen utama rantai serangan, yang mengandungi kemampuan jahat utama seperti pengumpulan kelayakan, penyebaran GitHub/npm, persistensi, perlawanan terhadap perlindungan, dan penyahkodan sumber terbenam.

Tiga sampel masing-masing menggunakan kunci AES-128-GCM, vektor inisialisasi, dan tag autentikasi yang berbeza untuk mengenkripsi kedua-dua komponen, tetapi SHA-256 bagi tiga pembimbing lingkungan Bun yang didekripsi semuanya ialah ac2a2208e1726e008be6c73dc0872d9bba163319259dff1b62055ac933ca46b6, dan SHA-256 bagi tiga beban berbahaya utama semuanya ialah 0dc06ecdaa63fe24859cfd955053c23245c536e4733480239d14bebf12688e35. Ini menunjukkan bahawa penyerang mengganti parameter pembungkusan luaran dalam pakej npm yang berbeza, tetapi menggunakan semula komponen berbahaya utama yang sama.

Selepas didekripsi, Tahap 2 akan menulis beban jahat utama ke /tmp, kemudian menjalankannya melalui Bun, dan akhirnya menghapus fail sementara. Logik sebenar yang dipulihkan daripada tiga sampel adalah seperti berikut:

Oleh itu, corak fail sementara yang boleh diverifikasi dalam tiga sampel ialah:

/tmp/p.js

Bun runtime bootloader berukuran 898 bytes, tiga sampel hash adalah identik:

ac2a2208e1726e008be6c73dc0872d9bba163319259dff1b62055ac933ca46b6

Penggerak persekitaran Bun mengandungi logik seperti child_process.execSync, fs.existsSync, fs.mkdtempSync, fs.chmodSync, os.platform(), os.arch(), getBunPath() untuk menentukan atau mempersiapkan persekitaran Bun. Dengan kata lain, Tahap 2 tidak hanya mengandaikan bahawa Bun telah dipasang secara global; di luar laluan persekitaran Bun, ia akan memuatkan penggerak persekitaran Bun terlebih dahulu, kemudian memanggil Bun melalui getBunPath() untuk menjalankan beban berbahaya utama.

4. Tahap ketiga: jadual string obfuscator.io

Beban jahat yang didekripsi bukanlah JavaScript teks biasa yang boleh dibaca terus, tetapi masih mengalami kekeliruan gaya obfuscator.io dengan jadual string. Lapisan ini mengumpulkan banyak string ke dalam array, kemudian memulihkannya melalui indeks masa berjalan dan logik putaran, menyebabkan analis tidak dapat mengambil API, laluan, dan nama konfigurasi kunci seterusnya sebelum jadual string dipulihkan sepenuhnya.

5. Peringkat keempat: B5 Enkripsi Rentetan Khusus

Selepas memulihkan jadual string obfuscator.io, masih terdapat satu lapisan enkripsi string khusus B5 di dalam beban jahat utama. Parameter berikut telah disahkan:

  • KDF: PBKDF2 (Password-Based Key Derivation Function 2)
  • Fungsi hash: SHA-256
  • Jumlah lelaran: 200000
  • panjang kunci: 32 bait
  • Bilangan pusingan dekripsi: 3
  • kata laluan:ba2c6ddb3672bdd6a611e6850b4f700b52aed3dab2f1b3d5f8c839d4a157a709
  • garam:5b26508dc0f1075a7c0b4d8aa464487e

Hasil setelah dinyahsulitkan adalah:

Di antaranya, B5 setelah didekripsi akan menunjukkan pelbagai rentetan teks biasa penting. Perlu diperhatikan bahawa sebahagian rentetan asalnya berada dalam jadual rentetan obfuscator.io, dan hanya akan boleh digrep secara langsung selepas kedua-dua langkah "penggantian jadual rentetan + dekripsi B5" selesai:

6. Lapisan terbenam tambahan: AES-256-GCM + gzip

Pembebanan jahat utama juga mengandungi sumber bersarang yang dienkripsi AES-256-GCM dan dikompresi gzip. Logik pemulihan menggunakan:

Sumber lampiran kunci yang telah dipecahkan dibahagikan kepada tiga kategori mengikut fungsi:

Pembacaan memori lintas platform:

Sumber-sumber jenis ini digunakan untuk membaca memori proses yang sedang berjalan. Kunci dan token dalam fail biasa masih boleh ditemui melalui pemeriksaan fail, tetapi CI/CD Runner atau alat pembangun akan menyimpan beberapa nilai sensitif sementara dalam memori semasa berjalan. Penyerang menyisipkan skrip baca memori untuk tiga platform—Linux, Windows, dan macOS—dengan tujuan mengambil secret sementara ini dari memori proses sebanyak mungkin di pelbagai sistem.

Konfigurasi berterusan:

Sumber-sumber ini digunakan untuk "meninggalkan titik pemicu backdoor". Dengan kata lain, walaupun proses pemasangan npm asal telah selesai, penyerang masih ingin kod jahat berjalan semula apabila pengembang membuka projek, memulakan penyunting, memasuki sesi Claude Code, atau selepas log masuk semula sistem. Oleh itu, sumber-sumber ini menargetkan konfigurasi peringkat projek dan mekanisme auto-start peringkat pengguna: konfigurasi peringkat projek lebih tersembunyi, manakala perkhidmatan peringkat sistem lebih sesuai untuk berjalan jangka panjang.

C2 dan penyebaran:

Sumber-sumber terbenam ini digunakan untuk mengendalikan saluran seterusnya dan membawa rahsia repositori. YZ dinyahsulitkan adalah pemantau carian commit GitHub, yang akan secara berkala mencari mesej commit dalam format firedalazer ., mengesahkan tanda tangan, kemudian memuat turun dan menjalankan kandungan Python jauh; zZ dinyahsulitkan adalah templat alur GitHub Actions bernama Run Copilot, yang akan menulis ${{ toJSON(secrets) }} ke dalam format-results.txt dan menghantar sebagai artefak. Yang pertama menyediakan saluran untuk mendapatkan/menjalankan tugas seterusnya, yang kedua menyediakan templat untuk membawa rahsia repositori melalui artefak GitHub Actions; penyuntikan alur, penantian pelaksanaan, dan muat turun artefak sebenar dilakukan oleh logik API GitHub yang disertakan dalam beban utama.

Analisis kemampuan beban jahat utama

Setelah melalui proses de-obfuscasi bertingkat, sampel akhirnya melepaskan dan menjalankan beban jahat utama. Semua analisis berikut ini difokuskan pada modul beban jahat utama, diuraikan secara bertahap mengikut lima peringkat: pengambilan data, penghantaran keluar, penyebaran, kekalan, dan perlawanan.

Bacaan memori GitHub Actions Runner:

Sampel mengandungi skrip baca memori untuk tiga platform: Linux, Windows, dan macOS, dengan kemampuan dump silang platform. Implementasi Linux dilakukan dengan membaca /proc//maps dan /proc//mem proses sasaran:

Logik pengaktifan aktif beban berbahaya utama menargetkan runner Linux GitHub Actions: apabila GITHUB_ACTIONS === "true" dan RUNNER_OS === "Linux", kod mencari proses Runner.Worker dan mengeksport memori, kemudian mengekstrak rahsia yang disamarkan dalam format "":{"value":"","isSecret":true}. Lintasan pengumpulan aktif yang dapat disahkan dalam ketiga-tiga sampel berfokus pada runner Linux, tetapi skrip untuk ketiga-tiga platform telah disisipkan.

2. Pengumpulan kredensial pengembang awan ganda:

Beban jahat utama mengandungi modul pengumpulan kredensial yang sistematik, yang merangkumi penyedia awan, persekitaran CI, konfigurasi tempatan pengembang, GitHub CLI, pengurus kata laluan, dan fail dompet.

Tujuan pengumpulan kredensial penyedia awan adalah:

Modul AWS juga mengandungi logik berkaitan ECS/IMDS (Instance Metadata Service)/STS WebIdentity.

Pengumpulan kredensial tempatan pembangun meliputi sasaran berikut:

Logik pengurus kata laluan diimplementasikan dalam kod sumber sebagai array runCommand(command, args), bukan penggabungan rentetan shell.

Modul pengumpulan kredensial ini meliputi pelbagai sasaran dari platform awan hingga pengembang tempatan; data sensitif yang dikumpulkan dipindahkan melalui mekanisme berikut.

3. GitHub API bocor dan dead-drop:

Beban jahat utama menggunakan API GitHub sebagai saluran utama untuk eksfiltrasi data. Permintaan menyamar sebagai User-Agent python-requests/2.31.0, dan selepas mengesahkan token melalui x-oauth-scopes (yang perlu mengandungi repo, public_repo, atau workflow), operasi eksfiltrasi dijalankan: mencipta repository (description tetap sebagai Miasma: The Spreading Blight), kemudian menulis data yang dicuri yang telah di-encode base64 melalui PUT /repos///contents/results/.

Selain itu, beban telah mengimplementasikan mekanisme dead-drop berdasarkan carian commit GitHub, dengan mendapatkan arahan C2 melalui carian penanda "thebeautifulmarchoftime " (atau "thebeautifulsnadsoftime"):

biarkan hasil = tunggu X9("thebeautifulmarchoftime ", xZ);

Sumber terbenam YZ.bin ialah pemantau commit GitHub yang berdiri sendiri, yang memantau secara berkala setiap 3600 saat untuk mencari mesej commit dalam format firedalazer. Selepas pengesahan tanda tangan, ia memuat turun dan menjalankan kandungan Python jauh. Ini membentuk saluran kawalan susulan yang berasingan daripada saluran utama.

Konfigurasi sender HTTP POST yang menargetkan endpoint api.anthropic.com dan v1/api juga terdapat dalam kod sumber. Field noop dalam konfigurasi ini ditetapkan sebagai true, bermakna ia tidak akan menghantar permintaan rangkaian sebenar jika tidak dimodifikasi secara luaran. Oleh itu, analisis statik hanya boleh mengesahkan kehadiran struktur kod ini, tetapi tidak membuktikan adanya tindakan eksternal ke API Anthropic yang aktif.

4. Repositori GitHub dan infeksi alur kerja:

Beban jahat utama boleh mengendalikan objek git repositori melalui API REST / GraphQL GitHub:

Workflow jahat yang dibina dengan beban yang menyamar sebagai rilis meminta kebenaran id-token: write, dan menukar token penerbitan npm melalui laluan OIDC (OpenID Connect). Pemboleh ubah persekitaran dan antara muka laluan OIDC ialah ACTIONS_ID_TOKEN_REQUEST_TOKEN, ACTIONS_ID_TOKEN_REQUEST_URL, dengan audience ditetapkan sebagai npm:registry.npmjs.org. Dari segi kod sumber, boleh disahkan bahawa beban tersebut mempunyai kemampuan untuk menyuntik workflow ke dalam repositori GitHub dan memanfaatkan OIDC / penerbitan tepercaya npm untuk mendapatkan kebenaran penerbitan.

Selain cara menyuntikkan workflow melalui git refs seperti yang disebutkan di atas, beban juga menyertakan mekanisme pengangkutan rahsia yang lebih tersembunyi: workflow GitHub Actions yang menyamar sebagai Run Copilot menulis ${{ toJSON(secrets) }} ke format-results.txt dan menghantar artifact. Berbanding dengan menulis rahsia secara langsung ke kandungan repositori, pendekatan ini lebih cenderung mengangkut data melalui hasil pelaksanaan workflow, dan pemeriksaan diff kod biasa mungkin tidak dapat melihat secara langsung kandungan rahsia yang dieksport.

5. Jalankan alur kerja Copilot melalui artifact untuk memindahkan rahsia:

Sumber terbenam zZ.bin adalah alur kerja GitHub Actions yang menyamar sebagai Copilot, yang menulis ${{ toJSON(secrets) }} ke format-results.txt dan mengunggahnya sebagai artefak.

Perilaku API GitHub yang berkaitan termasuk: mencipta/memperbaharui branch sementara → menulis blob workflow → menunggu run workflow → memuat turun zip artifact → membaca format-results.txt → menghapus run workflow dan branch sementara. Kata kunci perburuan yang berkaitan termasuk Run Copilot, VARIABLE_STORE, format-results, chore/add-codeql-static-analysis, .github/workflows/codeql.yml.

6. npm penyebaran diri:

Beban jahat utama mempunyai dua laluan pelepasan / penyebaran npm yang berasingan.

Laluan token npm: Muat melalui GET /-/npm/v1/tokens untuk menyenaraikan token npm pengguna semasa, saring token dengan bypass_2fa === true dan memiliki kebenaran penulisan pakej, gunakan token ini untuk menerbitkan secara automatik. bypass_2fa adalah medan metadata token, bukan parameter badan penerbitan.

Laluan GitHub Actions OIDC: Membaca pemboleh ubah persekitaran ACTIONS_ID_TOKEN_REQUEST_TOKEN dan ACTIONS_ID_TOKEN_REQUEST_URL, meminta token OIDC dengan audience npm:registry.npmjs.org, dan bertukar melalui antaramuka pertukaran token OIDC npm untuk mendapatkan kebenaran penerbitan.

Prosedur operasi pencemaran tarball ialah membongkar → menulis index.js jahat → mengubah package.json:

Di sini dibezakan dua jenis entri: Tiga sampel muat naik tempatan sendiri menggunakan preinstall: "node index.js" — pada masa ini, persekitaran pemasangan tidak memerlukan Bun dipasang terlebih dahulu, dan menggunakan Node.js sebagai entri awal lebih tersembunyi; semasa penyebaran diri yang mencemari pakej lain, ia menulis preinstall: "bun run index.js" dan menambahkan kebergantungan bun — kerana logik beban jahat utama bergantung pada API yang disediakan oleh runtime Bun (seperti Bun.gunzipSync dan Bun.file), dalam skenario penyebaran diri, ia perlu memastikan persekitaran sasaran telah memiliki Bun.

7. Mekanisme pemertahanan:

Beban jahat utama mengandungi empat cara pemertahanan, yang merangkumi direktori projek dan permulaan automatik peringkat sistem.

Claude Code SessionStart hook: Sisipkan sumber daya S8.bin untuk menulis hook SessionStart ke .claude/settings.json, yang akan menjalankan node .claude/setup.mjs secara automatik setiap kali sesi Claude Code dimulai. Beban berbahaya juga ditulis ke .claude/setup.mjs dan .claude/index.js (laluan disusun dari ".claude/" + M0, M0 = "index.js").

Tugas folderOpen VS Code: Sisipkan sumber EZ.bin untuk menulis tugas folderOpen ke .vscode/tasks.json, dan menjalankan skrip yang sama secara automatik apabila folder projek yang terjejas dibuka. Juga tulis ke .vscode/setup.mjs.

kitty-monitor (systemd / LaunchAgent): Menanam sumber daya RZ.bin untuk memasang perkhidmatan persisten, fail tersebar di /.local/share/kitty/cat.py, /.config/systemd/user/kitty-monitor.service (Linux), dan ~/Library/LaunchAgents/com.user.kitty-monitor.plist (macOS). Beban jahat mencipta direktori /tmp/kitty-, menulis YZ.bin (pemantau komit GitHub) ke cat.py, kemudian memasangnya melalui RZ.bin.

gh-token-monitor (systemd / LaunchAgent): Memasang perkhidmatan pemantau token GitHub dengan sumber terbenam jZ.bin, fail-fail tersebar di /.local/bin/gh-token-monitor.sh, /.config/gh-token-monitor/, dan laluan systemd / LaunchAgent yang berkaitan. Pemantau ini mengesan sama ada token GitHub mengembalikan kod status 40x serta sama ada metadata paket npm @cap-js/openapi@1.4.1 tidak normal; apabila dipicu, ia akan menjalankan handler:

Ini bermakna apabila monitor mengesan GitHub API mengembalikan kod status 40x, seperti token dicabut, tidak sah, atau status kebenaran tidak normal, skrip jahat akan menjalankan handler yang dimasukkan. Handler yang dipulihkan daripada tiga sampel dalam artikel ini ialah rm -rf ~/; rm -rf ~/Documents. Semasa penanganan, jangan cabut token secara langsung pada hos yang mungkin masih menjalankan payload—sepatutnya isolasi hos terlebih dahulu, bersihkan item persisten dan proses yang sedang berjalan, kemudian ganti kredensial daripada persekitaran yang bersih.

8. Harden-Runner / StepSecurity:

Beban jahat utama mengandungi logik pengesanan dan perusakan terhadap StepSecurity Harden-Runner, yang membolehkan memintas perlindungan CI/CD melalui langkah-langkah berikut:

  1. Mengesan sama ada soket Docker /var/run/docker.sock boleh digunakan;
  2. Senaraikan kontainer Docker yang sepadan dengan kata kunci harden-runner / stepsecurity dalam nama atau imej;
  3. Tamatkan kontainer yang sepadan melalui POST /containers//kill;
  4. Cipta kontainer alpine bermula, tulis semula sudoers sebagai runner ALL=(ALL) NOPASSWD:ALL;
  5. Tulis entri penyelesaian tidak sah untuk domain terkait StepSecurity ke /etc/hosts;
  6. Tindih /etc/resolv.conf dengan 8.8.8.8 dan 1.1.1.1.

Logik pertembungan ini menunjukkan bahawa sampel tersebut disesuaikan khusus untuk persekitaran CI/CD yang dilindungi oleh StepSecurity.

9. EDR / Pemprosesan produk keselamatan, penilaian persekitaran, dan pengelakan:

Beban berbahaya utama mengesan nama proses dan laluan pemasaran pelbagai produk EDR (Endpoint Detection and Response) / keselamatan:

Beban juga mengandung logik pengelakan wilayah: mengesan pemboleh ubah persekitaran LC_ALL, LC_MESSAGES, LANGUAGE, LANG, jika setelah ditukar ke huruf kecil bermula dengan ru, maka akan dilewati. Sokongan pengenalan persekitaran CI termasuk GitHub Actions, GitLab CI, Travis CI, CircleCI, Jenkins, AWS CodeBuild, Buildkite, AppVeyor, Bitbucket, Drone, TeamCity, Cirrus CI dan sebagainya. Tanda status yang digunakan semasa berjalan termasuk tmp.0987654321.lock, __IS_DAEMON (menandakan proses anak daemon terpisah), SKIP_DOMAIN (melangkau laluan penghantar domain), /tmp/kitty-*, cat.py dan /var/tmp/.gh_update_state.

Analisis kesan

Dari segi kemampuan sumber kod, kesan ketiga-tiga sampel ini tidak terhad kepada pelaksanaan sekali sahaja pada peringkat pemasangan npm. Risiko sebenarnya boleh dibahagikan kepada empat peringkat:

Pada peringkat hos pembangun. Sampel akan mengumpul pemboleh ubah persekitaran, .npmrc, .pypirc, kunci SSH, konfigurasi Docker, .env, token CLI GitHub, data pengurus kata laluan, dan fail dompet, serta mengekalkan keupayaan pemicuan susulan melalui Claude Code, VS Code, perkhidmatan pengguna systemd, atau macOS LaunchAgent.

Pada peringkat CI/CD Runner. Sampel akan mengenal pasti GitHub Actions Linux runner, membaca memori proses Runner.Worker dan mengekstrak rahsia yang disamarkan; selain itu, ia juga mempunyai logik perlawanan terhadap StepSecurity Harden-Runner, cuba merosakkan atau memintas komponen perlindungan CI/CD.

Pada tahap organisasi dan repositori GitHub. Sampel boleh mencipta repositori, menulis ke contents/results/, mengendalikan git refs/blobs/trees/commits, menyuntik workflow jahat, serta mengangkut rahsia melalui Run Copilot workflow + artifact.

Tahap penyebaran ekosistem npm. Sampel boleh dipilih berdasarkan token npm yang mempunyai kebenaran write package dan bypass_2fa === true, atau boleh memanfaatkan laluan GitHub Actions OIDC / npm trusted publishing untuk mendapatkan keupayaan penerbitan; seterusnya, muat turun tarball sasaran, tulis loader jahat, ubah preinstall, tambah bergantung pada Bun, tingkatkan versi patch, dan terbitkan, membentuk rantai penyebaran sendiri di npm.

Ringkasan

Bukti kod sumber daripada tiga sampel menunjukkan bahawa pakej jahat ini bukan sekadar skrip pencurian maklumat pada masa pemasangan, tetapi merupakan gabungan loader berbilang peringkat dan implant penuh: lapisan luar dirandomisasi mengikut pakej, penggerak persekitaran Bun dan beban jahat utama tetap konsisten; implant utama merangkumi pelbagai tahap seperti pengumpulan kredensial, pengekstrakan rahsia CI, penyebaran GitHub/npm, persistensi, dan perlawanan terhadap perlindungan.

Reka bentuk pintu masuk yang sangat sulit dikesan. Penyerang tidak menyisipkan logik jahat dalam kod perniagaan, tetapi memasang loader yang disamarkan dalam skrip hayat npm. Loader ini terutamanya bertanggungjawab untuk menghuraikan dan menjalankan beban terbenam, menjadikan pemeriksaan sumber kod perniagaan sukar untuk mengenal pasti kemampuan sebenar.

Rantaian de-obfuscation bersarang lima lapisan. Beban jahat melalui lima lapisan pembungkusan: array nombor + penggantian huruf ROT, enkripsi AES-128-GCM, kekeliruan obfuscator.io, enkripsi string buatan sendiri B5, dan lapisan bersarang AES-256-GCM + gzip. Kunci atau parameter setiap lapisan boleh berubah secara bebas dalam pakej yang berbeza, menjadikan pengesanan berjumlah berdasarkan ciri statik lebih sukar.

Kemampuan serangan peringkat organisasi yang lengkap. Implan ini memiliki kemampuan membaca memori GitHub Actions Runner, mengumpulkan kredensial multi-cloud dan tempatan, menghantar data melalui GitHub API dan dead-drop, menginfeksi repositori dan workflow GitHub, penyebaran sendiri melalui npm, persistensi, dan perlawanan terhadap perlindungan. Dari struktur sumber kodnya, ia telah memiliki laluan kod yang mampu memicu penyebaran lanjutan dari pemasangan tunggal ke repositori, CI/CD, dan rantai penerbitan npm; lingkup penyebaran sebenar masih perlu dikonfirmasi bersama log pemasangan, audit repositori, dan telemetri sisi platform.

Bukti dari kod sumber mengesahkan bahawa ketiga-tiga sampel tersebut secara automatik dipicu melalui preinstall dan menyahsulit serta menjalankan implant utama yang sama. Namun, tidak dapat dibuktikan hanya dengan tiga sampel tgz ini bagaimana kuasa awal diperoleh dalam kes sebenar.

Cadangan tindakan

  1. Tinjau dan buang versi jahat dalam ketergantungan projek, fail lock, cache registry peribadi, dan cache pembinaan.
  2. Semak log pemasangan untuk melihat sama ada terdapat preinstall, node index.js, bun run, /tmp/p*.js, tmp.0987654321.lock.
  3. Jangan secara langsung mencabut token pada hos mangsa yang masih mungkin menjalankan payload. Disarankan untuk mengasingkan hos mangsa terlebih dahulu, membersihkan proses yang sedang berjalan dan item persisten, kemudian mengganti token yang berkaitan dengan GitHub, npm, kredensial awan, Kubernetes, Vault, SSH, Docker registry, dan pengurus kata laluan dari persekitaran bersih.
  4. Semak repositori GitHub terkini mengenai branch, commit, workflow, artifact, dan repositori baharu, dengan fokus pada kata kunci seperti Run Copilot, format-results, chore/add-codeql-static-analysis, .github/workflows/codeql.yml, OIDC_PACKAGES.
  5. Semak sama ada direktori projek telah ditambah atau diubah: .claude/settings.json, .claude/setup.mjs, .vscode/tasks.json, .vscode/setup.mjs.
  6. Semak pengapungan peringkat pengguna: /.local/share/kitty/cat.py, /.config/systemd/user/kitty-monitor.service, ~/Library/LaunchAgents/com.user.kitty-monitor.plist, fail berkaitan gh-token-monitor.
  7. Semak sejarah npm publish, pastikan tiada penerbitan versi patch tanpa kebenaran; semak metadata token npm, fokus pada token yang boleh melangkau 2FA (Two-Factor Authentication) dan mempunyai kebenaran penulisan paket.
  8. Lakukan audit integriti terhadap produk hilir yang dibina dalam persekitaran yang tercemar.

IOC

Fail jahat

nama fail: redhat-cloud-services-frontend-components-config-6.11.3.tgz MD5: 633ad8849a59e2bfb7a0fe589e816a07 SHA1: 675294612f455fe6a9acb195f0cbe3687d8e2e34 SHA256: 0c9c67ec40d5f23efa1ec3470d0ac88b4993ccc0e92be913fc29a337dfc4f060

nama fail: redhat-cloud-services-types-3.6.1.tgz MD5: 9e6c5af01438b52c9a411686c1f1b8ff SHA1: 88d098c8d96e9ae17550e9798c3b62c420464b8c SHA256: d543bb3cdf1569c2b3d38c8a4081ed746cfe78bf3236c2302704d79ab7fa9558

nama fail: redhat-cloud-services-rule-components-4.7.2.tgz MD5: f1ffdbf5e639899f26a6ebab2eec408d SHA1: f3c5c21274045ae02fef11e931de6dcf8462a067 SHA256: aaf00d06baa3c679b82452c50014e9824b8874e9ca2d150f19095f8de19ba90f

SHA256

ac2a2208e1726e008be6c73dc0872d9bba163319259dff1b62055ac933ca46b6

0dc06ecdaa63fe24859cfd955053c23245c536e4733480239d14bebf12688e35

Ketergantungan jahat

npm:@redhat-cloud-services/topological-inventory-client@3.0.10

npm:@redhat-cloud-services/topological-inventory-client@3.0.11

npm:@redhat-cloud-services/topological-inventory-client@3.0.13

npm:@redhat-cloud-services/compliance-client@4.0.3

npm:@redhat-cloud-services/compliance-client@4.0.4

npm:@redhat-cloud-services/compliance-client@4.0.6

npm:@redhat-cloud-services/rbac-client@9.0.3

npm:@redhat-cloud-services/rbac-client@9.0.4

npm:@redhat-cloud-services/rbac-client@9.0.6

npm:@redhat-cloud-services/insights-client@4.0.4

npm:@redhat-cloud-services/insights-client@4.0.5

npm:@redhat-cloud-services/insights-client@4.0.7

npm:@redhat-cloud-services/frontend-components@7.7.2

npm:@redhat-cloud-services/frontend-components@7.7.3

npm:@redhat-cloud-services/frontend-components@7.7.5

npm:@redhat-cloud-services/frontend-components-utilities@7.4.1

npm:@redhat-cloud-services/frontend-components-utilities@7.4.2

npm:@redhat-cloud-services/frontend-components-utilities@7.4.4

npm:@redhat-cloud-services/remediations-client@4.0.4

npm:@redhat-cloud-services/remediations-client@4.0.5

npm:@redhat-cloud-services/remediations-client@4.0.7

npm:@redhat-cloud-services/frontend-components-notifications@6.9.2

npm:@redhat-cloud-services/frontend-components-notifications@6.9.3

npm:@redhat-cloud-services/frontend-components-notifications@6.9.5

npm:@redhat-cloud-services/patch-client@4.0.4

npm:@redhat-cloud-services/patch-client@4.0.5

npm:@redhat-cloud-services/patch-client@4.0.7

npm:@redhat-cloud-services/host-inventory-client@5.0.3

npm:@redhat-cloud-services/host-inventory-client@5.0.4

npm:@redhat-cloud-services/host-inventory-client@5.0.6

npm:@redhat-cloud-services/rule-components@4.7.2

npm:@redhat-cloud-services/rule-components@4.7.3

npm:@redhat-cloud-services/rule-components@4.7.5

npm:@redhat-cloud-services/frontend-components-advisor-components@3.8.2

npm:@redhat-cloud-services/frontend-components-advisor-components@3.8.4

npm:@redhat-cloud-services/frontend-components-advisor-components@3.8.6

npm:@redhat-cloud-services/notifications-client@6.1.4

npm:@redhat-cloud-services/notifications-client@6.1.5

npm:@redhat-cloud-services/notifications-client@6.1.7

npm:@redhat-cloud-services/sources-client@3.0.10

npm:@redhat-cloud-services/sources-client@3.0.11

npm:@redhat-cloud-services/sources-client@3.0.13

npm:@redhat-cloud-services/integrations-client@6.0.4

npm:@redhat-cloud-services/integrations-client@6.0.5

npm:@redhat-cloud-services/integrations-client@6.0.7

npm:@redhat-cloud-services/frontend-components-config@6.11.3

npm:@redhat-cloud-services/frontend-components-config@6.11.4

npm:@redhat-cloud-services/frontend-components-config@6.11.6

npm:@redhat-cloud-services/frontend-components-config-utilities@4.11.2

npm:@redhat-cloud-services/frontend-components-config-utilities@4.11.3

npm:@redhat-cloud-services/frontend-components-config-utilities@4.11.5

npm:@redhat-cloud-services/hcc-pf-mcp@0.6.1

npm:@redhat-cloud-services/hcc-pf-mcp@0.6.2

npm:@redhat-cloud-services/hcc-pf-mcp@0.6.4

npm:@redhat-cloud-services/frontend-components-remediations@4.9.2

npm:@redhat-cloud-services/frontend-components-remediations@4.9.3

npm:@redhat-cloud-services/frontend-components-remediations@4.9.5

npm:@redhat-cloud-services/eslint-config-redhat-cloud-services@3.2.1

npm:@redhat-cloud-services/eslint-config-redhat-cloud-services@3.2.2

npm:@redhat-cloud-services/eslint-config-redhat-cloud-services@3.2.4

npm:@redhat-cloud-services/javascript-clients-shared@2.0.8

npm:@redhat-cloud-services/javascript-clients-shared@2.0.9

npm:@redhat-cloud-services/javascript-clients-shared@2.0.11

npm:@redhat-cloud-services/quickstarts-client@4.0.11

npm:@redhat-cloud-services/quickstarts-client@4.0.12

npm:@redhat-cloud-services/quickstarts-client@4.0.14

npm:@redhat-cloud-services/config-manager-client@5.0.4

npm:@redhat-cloud-services/config-manager-client@5.0.5

npm:@redhat-cloud-services/config-manager-client@5.0.7

npm:@redhat-cloud-services/hcc-feo-mcp@0.3.1

npm:@redhat-cloud-services/hcc-feo-mcp@0.3.2

npm:@redhat-cloud-services/hcc-feo-mcp@0.3.4

npm:@redhat-cloud-services/entitlements-client@4.0.11

npm:@redhat-cloud-services/entitlements-client@4.0.12

npm:@redhat-cloud-services/entitlements-client@4.0.14

npm:@redhat-cloud-services/tsc-transform-imports@1.2.2

npm:@redhat-cloud-services/tsc-transform-imports@1.2.4

npm:@redhat-cloud-services/tsc-transform-imports@1.2.6

npm:@redhat-cloud-services/hcc-kessel-mcp@0.3.1

npm:@redhat-cloud-services/hcc-kessel-mcp@0.3.2

npm:@redhat-cloud-services/hcc-kessel-mcp@0.3.4

npm:@redhat-cloud-services/frontend-components-testing@1.2.1

npm:@redhat-cloud-services/frontend-components-testing@1.2.2

npm:@redhat-cloud-services/frontend-components-testing@1.2.4

npm:@redhat-cloud-services/types@3.6.1

npm:@redhat-cloud-services/types@3.6.2

npm:@redhat-cloud-services/types@3.6.4

npm:@redhat-cloud-services/chrome@2.3.1

npm:@redhat-cloud-services/chrome@2.3.2

npm:@redhat-cloud-services/chrome@2.3.4

npm:@redhat-cloud-services/frontend-components-translations@4.4.1

npm:@redhat-cloud-services/frontend-components-translations@4.4.2

npm:@redhat-cloud-services/frontend-components-translations@4.4.4

npm:@redhat-cloud-services/vulnerabilities-client@2.1.8

npm:@redhat-cloud-services/vulnerabilities-client@2.1.9

npm:@redhat-cloud-services/vulnerabilities-client@2.1.11

Penafian: Maklumat yang terdapat pada halaman ini mungkin telah diperoleh daripada pihak ketiga dan tidak semestinya menggambarkan pandangan atau pendapat KuCoin. Kandungan ini adalah disediakan bagi tujuan maklumat umum sahaja, tanpa sebarang perwakilan atau waranti dalam apa jua bentuk, dan juga tidak boleh ditafsirkan sebagai nasihat kewangan atau pelaburan. KuCoin tidak akan bertanggungjawab untuk sebarang kesilapan atau pengabaian, atau untuk sebarang akibat yang terhasil daripada penggunaan maklumat ini. Pelaburan dalam aset digital boleh membawa risiko. Sila menilai risiko produk dan toleransi risiko anda dengan teliti berdasarkan keadaan kewangan anda sendiri. Untuk maklumat lanjut, sila rujuk kepada Terma Penggunaan dan Pendedahan Risiko kami.