«Фриланс на 800 тысяч». Как “вакансия” в LinkedIn оказалась попыткой заразить компьютер разработчика

«Фриланс на 800 тысяч». Как “вакансия” в LinkedIn оказалась попыткой заразить компьютер разработчика

Какая деталь в профиле рекрутера должна была насторожить сразу?

image

Разработчик Дэниел Тофан рассказал о попытке заразить его компьютер через «выгодное» предложение работы в LinkedIn. 21 января 2026 года ему написали по поводу фриланс-проекта для якобы британской платформы в сфере недвижимости с бюджетом 600-800 тыс. долларов и попросили «оценить кодовую базу». Профиль выглядел правдоподобно: 500+ контактов, значок верификации, указана компания и должность. Позже автор заметил деталь, которая должна была насторожить сразу: при большом числе связей у аккаунта не было ни одного поста или активности.

Вместо обычного тестового задания собеседник прислал ссылку на репозиторий GitLab с React/Node.js приложением и дополнил это документацией в Notion. Код действительно выглядел «живым»: структура проекта, фронтенд с визуализациями, бэкенд на Express, интеграции вроде MongoDB и SendGrid. Но эта реалистичность оказалась ширмой для целевой атаки на цепочку поставок: в проект встроили троянизированную логику, которая использует lifecycle-хуки npm и запускается автоматически при установке зависимостей.

Механика была простой и неприятной. В package.json атакующие прописали postinstall, который после npm install запускал start и поднимал сервер. Дальше срабатывал загрузчик, спрятанный в конце «обычного» файла контроллера: он декодировал Base64-строки из переменных окружения, вытаскивал URL, скачивал удаленный payload с легитимного хостинга JSON (jsonkeeper.com) и исполнял полученную строку кода через Function.constructor. По сути это была удаленная подгрузка и выполнение произвольного кода на машине жертвы, замаскированные под часть веб-приложения.

По описанию автора, удаленный payload состоял из нескольких модулей. Один поднимал канал управления и связи, устанавливая соединение socket.io с сервером 144.172.108.57:4891 и позволяя выполнять команды через child_process, второй искал по дискам «интересные» файлы вроде .env, ключей, документов и таблиц и отправлял их на http://144.172.108.57:4896/upload, третий следил за буфером обмена (в том числе через PowerShell) и пересылал содержимое на сторону атакующих. Инфраструктура, по данным расследования, была размещена у VPS-провайдера Cloudzy, а «британская недвижимость» выглядела как легенда - сам автор отдельно подчеркивает, что не видит доказательств причастности реальной компании, чье имя использовали в профиле.

После обнаружения закладки разработчик удалил клон репозитория, очистил локальную папку .npm, где могла появиться «персистентность», и в качестве меры предосторожности провернул ротацию множества ключей и токенов (от API сервисов до облаков и платежной инфраструктуры). Он также отправил жалобы в GitLab и LinkedIn и сохранил артефакты для отчета. 26 января GitLab ответил, что удалил репозиторий по обращению автора, но профиль в LinkedIn на момент публикации оставался активным.

Главный вывод этой истории - «обычный» код-ревью не равен аудиту безопасности, особенно когда речь идет о целевых атаках. Тофан пишет, что даже проверка с помощью ИИ сначала не увидела проблему и назвала проект «нормальным», и только после прямого запроса на поиск вредоносной логики модель обратила внимание на Base64, динамическое исполнение и подгрузку удаленного кода. Как базовые меры защиты он советует всегда просматривать npm-скрипты вроде postinstall/preinstall, настороженно относиться к eval/new Function/Function.constructor, декодировать подозрительные строки, искать использование child_process в веб-приложениях и, если уж нужно запускать чужой проект, делать это только в изолированной среде (песочнице, одноразовой VM или контейнере без доступа к файловой системе хоста).