Кампания PolinRider добралась до PHP-пакета с 700 тысячами загрузок: заражена ветка разработки

Кампания PolinRider добралась до PHP-пакета с 700 тысячами загрузок: заражена ветка разработки

В середине июня 2026 года неизвестные получили контроль над учётной записью разработчика на GitHub. Через неё в репозитории организации Visanduma внесли вредоносный код. Пострадал и пакет nova-two-factor, который добавляет двухфакторную аутентификацию в проекты на PHP. Суммарное число загрузок пакета превысило 700 тысяч. Опасность пока касается только нестабильных веток разработки, так называемых dev-версий. Стабильные релизы на момент проверки оставались чистыми.

Описание

Первое подробное описание кампании PolinRider появилось в июле. С тех пор её следы находили в каталогах пакетов npm (для JavaScript), PyPI (для Python), в модулях Go, в Packagist (для PHP) и даже в расширениях для Chrome. Платформы менялись, тактика оставалась прежней. Вредоносный код размещают в ветках, которые разработчики подключают напрямую во время работы. Те, кто устанавливает пакет обычным способом, пока защищены. Те, кто берёт код из ветки разработки, рискуют получить заражённую сборку.

Исследование Socket показало, что публикация вредоносного пакета редко бывает главной целью кампании. Чаще компрометация каталога становится следствием более широкого вторжения в репозитории на базе Git. Злоумышленники используют обычные инструменты совместной работы над кодом. Так они добираются до рабочих машин разработчиков, распространяются по другим проектам и закрепляются надолго. Публичная активность одной скомпрометированной учётной записи включает сотни изменений в закрытых репозиториях. Полный масштаб вторжения по открытым источникам оценить невозможно.

Схема опирается на четыре приёма. Первый - принудительная перезапись истории Git, которая затрудняет проверку правок и откат. Второй - маскировка: вредоносный код прячут в настройках проекта или в файлах, выдаваемых за шрифты. При вычитке такие вставки легко пропустить. Третий - автоматический запуск. Часть файлов срабатывает во время сборки, другие активируются, когда разработчик просто открывает проект в редакторе кода. Четвёртый - поэтапная доставка. Первый фрагмент кода находит адрес командно-контрольного сервера, а уже с него скачивается основная программа для кражи информации.

Проекты на PHP попадали в поле зрения PolinRider и раньше. До сих пор заражение шло через файлы конфигурации, куда внедряли код на JavaScript. Теперь появился новый вариант. Намеренно запутанный код помещают прямо во входной файл, который обрабатывает запросы к сайту. Точка входа в приложение сама инициирует цепочку заражения через функцию запуска сторонних команд. Такой поворот говорит о гибкости злоумышленников: способ запуска подбирают под возможности конкретного проекта.

Большинство атак на цепочку поставок устроены иначе. Их авторы торопятся: портят популярный пакет, выпускают вредоносную версию и ждут реакции защитников. PolinRider действует медленнее. Основной канал распространения - совместная работа над кодом в Git-сервисах. Публикация в каталоге пакетов становится лишь дополнительным путём. Модули Go и Packagist умеют забирать код напрямую из репозиториев. Заражённый исходник попадает в другую экосистему без кражи учётных данных для выпуска релизов.

Измерить урон от кампании целиком не получается. Поиск по открытому коду показывает лишь текущее состояние публичных репозиториев. Он не видит закрытые проекты, к которым получили доступ скомпрометированные аккаунты. Не видит репозитории, которые успели заразить и почистить. Не видит рабочие станции, где вредоносный код уже сработал. Очистка хранилища не гарантирует чистоту компьютеров и систем непрерывной интеграции. После запуска основной полезной нагрузки машина может оставаться заражённой независимо от состояния репозитория. Разработчики, столкнувшиеся с проблемой, сообщали о трудностях с удалением вредоносных компонентов.

Главная цель кампании - кража криптовалюты. Попутно вредоносные программы собирают учётные данные, исходный код и другие сведения, полезные для злоумышленников. Связь с северокорейскими операторами, которую отмечают в отрасли, делает быстрое сворачивание кампании маловероятным.

Для защиты стоит отказаться от установки пакета из ветки разработки, пока репозиторий не признают чистым. Зависимости лучше фиксировать на проверенном наборе изменений или на стабильном релизе. Проверять нужно не только текущее содержимое проекта, но и историю правок. Искать следует следы принудительной перезаписи истории, изменения в защите веток, правки настроек сборки и изменения от незнакомых учётных записей. Отдельного внимания требуют сценарии автоматического запуска задач при открытии проекта в редакторе кода. Если разработчик открывал заражённый проект или запускал его сборку, машину нужно изолировать и проверить. После срабатывания полезной нагрузки очистки репозитория мало, иногда требуется полная переустановка системы. Все доступные учётные данные - токены доступа, ключи шифрования, секреты криптовалютных кошельков - придётся заменить. Помимо этого, стоит ограничить принудительную отправку изменений, ввести обязательную проверку правок и запретить автоматический запуск задач из недоверенных проектов.

PolinRider держится не за конкретный пакет и не за отдельную платформу. Кампания встроилась в повседневную работу с кодом, поэтому переживает точечные блокировки. Свежий случай в Packagist показывает, что судить о её масштабе по видимым вредоносным релизам нельзя. Следы остаются в истории репозиториев, в закрытых проектах и на машинах разработчиков. Кампания продолжит меняться и осваивать новые приёмы, а её отслеживание потребует постоянного внимания к отклонениям в привычном процессе разработки.

Индикаторы компрометации

IPv4

  • 166.88.134.62
  • 166.88.73.46
  • 193.247.144.38
  • 23.27.13.135

Package

  • visanduma/nova-two-factor@dev-nova4support
  • visanduma/nova-two-factor@dev-main
  • visanduma/nova-two-factor@dev-using-inertia
  • visanduma/nova-two-factor@dev-nova5

Ethereum Address

  • 0xa322E5f3D311D3080e6f0121063e9aDC2490Ef1a

SHA256

  • 139ea03dcddf4aa810d55740be3cf6c92ce7a9f3cbcbbb35440e25b769a87683
  • 515a53291d25d229e1f9fa72e66407e1cfd7e77c91478400b24d5185af68531a
  • 7d47c430e6e404dc2fa8b4837678d1cbdb4d0aeacec9b405655cab79d54a2ad9
  • b7ede935d4979146b55f12b9eec7c83b61962b478f5dc9b8db251e539ec2abd3
  • ccb187dc9de0cc7477c9817ae53365d273e121407c0305f863e2ab67c35d6395

Комментарии: 0