Эксперты Microsoft Defender for Endpoint обнаружили целенаправленную кампанию, нацеленную на разработчиков программного обеспечения. Злоумышленники распространяют вредоносные репозитории, маскируя их под легитимные проекты на фреймворке Next.js и материалы для технического собеседования. Согласно телеметрии, собранной в ходе расследования, эта активность вписывается в более широкий кластер угроз, использующих приманки, связанные с поиском работы, чтобы встроиться в рутинные рабочие процессы разработчиков и повысить вероятность выполнения кода. Этот инцидент высвечивает растущую тенденцию атак на ключевое звено в цепочке создания программного обеспечения - самих инженеров, чьи рабочие станции часто содержат высокоценные активы, включая исходный код, ключи доступа к облачным средам и конфиденциальные переменные окружения.
Описание
Расследование началось с анализа подозрительных исходящих подключений к контролируемой злоумышленниками инфраструктуре командования и управления. Телеметрия Defender показала, что процессы Node.js неоднократно связывались с определёнными IP-адресами, что побудило специалистов по безопасности глубже изучить соответствующие цепочки выполнения. Корреляция сетевой активности с данными о процессах позволила отследить выполнение Node.js до вредоносных репозиториев, которые послужили первоначальным механизмом доставки. В частности, был идентифицирован репозиторий на платформе Bitbucket, представленный как техническое задание для соискателей, а также связанный с ним репозиторий, использующий соглашение об именовании Cryptan-Platform-MVP1.
На основе этих находок аналитики расширили область поиска, сфокусировавшись на общей структуре кода, логике загрузчика и шаблонах именования репозиториев. Были выявлены повторяемые соглашения: «семейства» репозиториев с именами вроде Cryptan, JP-soccer, RoyalJapan и SettleMint, а также варианты имен с использованием суффиксов v1, master, demo, platform и server. Структурное повторение, включая схожее размещение файлов и архитектуру загрузчика, подтвердило, что вновь обнаруженные репозитории функционально связаны, а не просто имеют похожие названия. Это позволило выявить дополнительные связанные репозитории, которые не фигурировали в исходной телеметрии, но демонстрировали то же поведение на этапах выполнения и подготовки.
Анализ выявленных репозиториев показал три повторяющихся пути выполнения, спроектированных для активации в ходе обычной деятельности разработчика. Примечательно, что, хотя каждый путь запускается разным действием, все они в конечном итоге сходятся к одному и тому же результату: динамическому получению и выполнению в памяти контролируемого злоумышленником JavaScript-кода, что ведёт к развёртыванию полноценной системы командования и управления. Первый путь злоупотребляет автоматизацией рабочей области в среде разработки Visual Studio Code. При открытии и доверии к проекту конфигурационный файл .vscode/tasks.json, настроенный с параметром runOn: "folderOpen", немедленно запускает задачу, инициирующую цепочку. В качестве резерва некоторые варианты включают в себя замаскированный JavaScript, обрабатываемый при инициализации рабочей области. В обоих случаях цепочка следует шаблону «получить-и-выполнить», загружая загрузчик JavaScript с платформы Vercel и исполняя его напрямую с помощью Node.js, после чего начинается отсылка сигналов на контролируемую атакующими инфраструктуру.
Второй путь выполнения активируется, когда разработчик вручную запускает приложение, например, командой npm run dev или прямым стартом сервера. В этих вариантах вредоносная логика внедрена в ресурсы приложения, которые выглядят легитимно, но троянизированы для работы в качестве загрузчиков. Распространёнными примерами являются модифицированные JavaScript-библиотеки, такие как jquery.min.js, содержащие замаскированный код вместо стандартной функциональности библиотеки. При запуске сервера разработки троянизированный ресурс декодирует URL, закодированный в формате base64, и загружает загрузчик, размещённый на Vercel. Затем полученная полезная нагрузка выполняется в памяти процессом Node.js, что приводит к тому же поведению бэкдора, что и в других сценариях. Этот механизм обеспечивает избыточность, гарантируя выполнение даже когда автоматизация на уровне редактора кода не срабатывает.
Третий путь активируется при запуске серверной части приложения. Здесь вредоносная логика загрузчика встроена в бэкенд-модули или маршруты, которые выполняются при инициализации сервера или импорте модуля. Репозитории часто включают значение в файле .env, содержащее конечную точку в кодировке base64, и соответствующий файл маршрута на сервере, который реализует загрузчик. При старте загрузчик декодирует конечную точку, передаёт переменные окружения процесса на сервер атакующего, а затем выполняет JavaScript, полученный в ответе, используя динамическую компиляцию. Это приводит к удалённому выполнению кода в памяти процесса Node.js, что может раскрыть чувствительные конфигурации, такие как облачные ключи, учётные данные баз данных и API-токены, и позволяет выполнять последующие команды даже в средах, где не срабатывают первые два механизма.
Независимо от начального пути, все три механизма ведут к одной и той же нагрузке первого этапа, которая функционирует как облегчённый регистратор и канал начальной загрузки. После получения со staging-инфраструктуры скрипт профилирует хост и периодически опрашивает конечную точку регистрации. Ответ сервера может предоставить устойчивый идентификатор, который используется в последующих опросах для корреляции активности. При определённых ответах клиент также выполняет предоставленный сервером JavaScript в памяти, используя динамическую компиляцию, что позволяет проводить начальную настройку по запросу без записи дополнительных нагрузок на диск.
Второй этап превращает первоначальную точку опоры в постоянного, управляемого оператором клиента для выполнения задач. В отличие от первого этапа, второй этап взаимодействует с отдельным IP-адресом C2 и набором API, предоставленным в ходе начальной загрузки. Полезная нагрузка обычно выполняется как встроенный скрипт, а затем остаётся активной в виде длительного цикла управления. Контроллер опрашивает конечную точку задач и получает массив JavaScript-задач. Он поддерживает состояние сессии между раундами, может обновлять идентификаторы во время выполнения задач и реагировать на команду остановки. Получив задачи, контроллер выполняет их в памяти с помощью отдельного интерпретатора Node, что помогает сократить количество артефактов на диске. Кроме выполнения кода по требованию, второй этап поддерживает разведку, управляемую оператором, и эксфильтрацию данных. Наблюдаемые операции включали просмотр каталогов через парные конечные точки перечисления, а также поэтапную процедуру загрузки для передачи собранных файлов.
Данная кампания наглядно демонстрирует, как проект для собеседования, оформленный в теме рекрутинга, может быстро превратиться в надёжный путь к удалённому выполнению кода, маскируясь под рутинные действия разработчика. Целью является получение контроля над системами разработчиков, которые часто содержат высокоценные активы. Когда недоверенные проекты для оценки запускаются на корпоративных устройствах, последующий компрометас может выйти за рамки одной конечной точки. Ключевой вывод для специалистов по безопасности заключается в том, что рабочие процессы разработки следует рассматривать как первичную поверхность атаки. Необходимо уделять приоритетное внимание мониторингу необычного выполнения Node.js, неожиданных исходящих подключений, а также последующей разведывательной активности или поведения, связанного с выгрузкой данных, исходящего с машин разработчиков. Для митигации подобных угроз рекомендуется ужесточить политики доверия для внешних репозиториев, внедрить сегментацию сетевого доступа для сред разработки, а также настроить правила обнаружения в системах класса SIEM (Security Information and Event Management) для аномальной сетевой активности Node.js-процессов, особенно к таким платформам, как Vercel, в нестандартных контекстах.
Индикаторы компрометации
IPv4
- 147.124.202.208
- 163.245.194.216
- 66.235.168.136
- 87.236.177.9
Domains
- api-web3-auth.vercel.app
- coredeal2.vercel.app
- ip-checking-notification-firebase111.vercel.app
- ip-checking-notification-kgm.vercel.app
- ip-check-notification-03.vercel.app
- ip-check-notification-firebase.vercel.app
- ip-check-notification-firebase03.vercel.app
- ip-check-notification-rkb.vercel.app
- ip-check-wh.vercel.app
- monobyte-code.vercel.app
- oracle-v1-beta.vercel.app
- price-oracle-v2.vercel.app
- vscodesettingtask.vercel.app
URLs
- http://147.124.202.208:3000/api/reportErrors
- http://87.236.177.9:3000/api/errorMessage
- http://87.236.177.9:3000/api/handleErrors
- http://87.236.177.9:3000/api/hsocketNext
- http://87.236.177.9:3000/api/hsocketResult
- http://87.236.177.9:3000/api/reportErrors
- http://87.236.177.9:3000/upload
- http://87.236.177.9:3000/uploadend
- http://87.236.177.9:3000/uploadsecond
- http://api-web3-auth.vercel.app/api/auth
- https://api.ipify.org/?format=json
- https://coredeal2.vercel.app/api/auth
- https://ip-checking-notification-firebase111.vercel.app/api
- https://ip-check-notification-03.vercel.app/api
- https://ip-check-notification-firebase.vercel.app/api
- https://ip-check-notification-firebase03.vercel.app/api
- https://ip-check-notification-rkb.vercel.app/api
- https://ip-check-wh.vercel.app/api
- https://oracle-v1-beta.vercel.app/api/getMoralisData
- https://price-oracle-v2.vercel.app
- https://vscodesettingtask.vercel.app/api/settings/XXXXX
SHA256
- 07ad8525844ce61471e08e8c515b76bf063bac482394152bad814026cd577f69
- 13152dcb3be425e1ce0f085cd733121a4665cf9935cf8867738e3d510a80308a
- 449e2bf57ab4790427a3a7de3d98b6c540e76190a3d844de2f0e7b66be842b19
- 6d59740d0710da370d5c38ddf88d6912487a1799e4ad09b72d764a3d27ed16b3
- ddd43e493cb333c1cc5d7cd50a6a5a61ecd89cfa5f4076f62c2adf96748b87f8
- e4d71aa95be0725c351e9d1d273d35ccdb0a8bdb31a57927c8738431b89788f5
