Масштабная атака на цепочку поставок затронула три популярных WordPress-плагина для маркетинга и конверсий - OptinMonster, TrustPulse и PushEngage. Все они входят в экосистему компании Awesome Motive и установлены на огромном количестве сайтов. По оценкам исследователей Sansec, потенциально уязвимыми оказались более 1,2 миллиона веб-ресурсов. Вредоносный код не внедрялся через уязвимость самих плагинов. Злоумышленники скомпрометировали серверы вендора и изменили JavaScript-файлы, которые доставлялись с CDN (сети доставки контента) на живые сайты. В результате код выполнялся в браузере любого вошедшего администратора, который загружал страницу с изменённым скриптом.
Описание
Интерес этой кампании в том, что инъекция действует на стороне клиента, используя действительные учётные данные и одноразовый токен (nonce) администратора. Каждый вредоносный запрос на сетевом уровне выглядит почти как легитимное действие настоящего администратора, создающего нового пользователя. Именно это сделало атаку труднообнаружимой и сложной для блокировки без нарушения нормальной функциональности.
Согласно официальному раскрытию компании OptinMonster, злоумышленник использовал уязвимость в стороннем плагине UpdraftPlus, установленном на маркетинговом сайте OptinMonster. Получив доступ к серверу, он похитил API-ключ CDN и с его помощью изменил JavaScript-файлы, которые раздавались клиентам с граничных узлов CDN. Изменённые файлы представляли собой фронтенд-наборы для разработки (SDK) плагинов. Вредоносный код был добавлен в конец легитимного минифицированного SDK, поэтому файл продолжал нормально работать, а логика атакующего выполнялась параллельно. Обновление самих плагинов не выпускалось - изменение произошло полностью на стороне CDN, и полностью обновлённый сайт мог получить вредоносный скрипт.
Хронология событий показывает тщательную подготовку. 28 апреля 2026 года был зарегистрирован домен командного сервера tidio[.]cc и выпущен TLS-сертификат. 12 июня в 22:17 UTC вредоносное содержимое впервые обнаружено в файлах OptinMonster и TrustPulse. Уже в 22:42 UTC его последний раз зафиксировали на CDN этих плагинов. 13 июня в 19:02 UTC SDK PushEngage на некоторых граничных узлах CDN всё ещё содержал инжектированный код. 14 июня вредонос был удалён, и OptinMonster опубликовал уведомление об инциденте. В течение 14-15 июня правила блокировки Patchstack активно предотвращали попытки автоматической эксплуатации на защищённых сайтах. Окно воздействия для OptinMonster и TrustPulse оказалось коротким, но изменённый SDK PushEngage задержался на некоторых узлах CDN до 13-14 июня, пока очищались кеши.
Анализ захваченного вредоносного кода показывает тщательно продуманную многоэтапную процедуру. Скрипт сначала проверяет окружение, чтобы избежать исследователей и автоматизированных инструментов. Он ищет признаки headless-браузера, нулевой размер окна, а затем убеждается, что выполняется в контексте администратора WordPress по наличию админ-панели, пути /wp-admin/ и cookie wordpress_logged_in_. Если перед ним не вошедший администратор, скрипт останавливается. Он также устанавливает метку в localStorage, чтобы не запускаться повторно в том же браузере в течение 24 часов. Затем код определяет корневой путь WordPress и извлекает одноразовый токен REST API. С ним и куками администратора скрипт может делать аутентифицированные запросы от имени администратора.
Ключевой этап - создание учётной записи администратора. Скрипт последовательно пробует несколько методов: REST API, стандартную форму user-new.php, AJAX-запрос и, наконец, скрытый iframe. Он создаёт как фиксированную учётную запись developer_api1 / customer1usx[@]gmail.com, так и рандомизированные варианты dev_xxxxxx / dev_xxxxxx[@]gmail.com. Вредоносная нагрузка содержит словарь сообщений об уже существующем пользователе на разных языках, чтобы корректно обработать ситуацию, если учётная запись уже создана. После получения прав администратора скрипт загружает ZIP-архив с командного сервера и устанавливает его как плагин, маскируясь под безобидные названия вроде "Content Delivery Helper" или "Database Optimizer". Этот бэкдор активно скрывает себя из списка плагинов, пользователей и журналов активности. Он предоставляет веб-шелл для выполнения произвольных команд и точку входа для выполнения кода, декодированного из base64. Результаты эксфильтрации шифруются с помощью XOR и отправляются на командный сервер через цепочку методов: navigator.sendBeacon, fetch, XMLHttpRequest и, в крайнем случае, через пиксельное изображение.
Важный вывод: это не CSRF и не ошибка в плагине. Вредоносные запросы несут легитимную сессию администратора и легитимный одноразовый токен, потому что браузер самого администратора их отправляет. Администратор становится жертвой, а не атакующим.
В телеметрии Patchstack зафиксировано, что с 14 по 15 июня 2026 года правило блокировки остановило 271 запрос на 13 различных сайтах, пришедших с 81 уникального IP-адреса. Подавляющее большинство попыток - 263 - направлялись на создание учётной записи через REST API. Ещё пять попыток пришлось на форму user-new.php, а три - на AJAX. Из этих 271 запроса 267 использовали рандомизированные идентификаторы dev_xxxxxx, и только четыре - фиксированные developer_api1. Версия, распространяемая в масштабе, явно отдавала предпочтение случайным именам, тогда как фиксированные идентификаторы встречались в основном через форму.
Характер трафика говорит сам за себя. Запросы приходили с 81 различных IP-адресов, принадлежащих домашним абонентам, а не централизованным серверам. Около 60% браузеров составляли мобильные (Android/Samsung), остальные - Windows, macOS и Linux, включая несколько строк User-Agent от Googlebot. Это именно то, что ожидаешь, когда вредоносный код выполняется в браузерах реальных администраторов сайтов, а не с единого сервера атакующего. Сайты подвергались быстрым всплескам попыток - на отдельных ресурсах регистрировались серии запросов на создание учётных записей с интервалом в секунды, пока скрипт проходил по своему цепочке запасных методов. Два сайта только зафиксировали почти 200 заблокированных попыток.
Межсетевой экран на уровне веб-приложений не может предотвратить загрузку скомпрометированного скрипта CDN браузером и не видит зашифрованные сигналы на tidio[.]cc. Однако он способен блокировать действия, которые нагрузка выполняет на сайте, сопоставляя жёстко заданные индикаторы атакующего. Patchstack развернул правило, которое блокирует создание учётной записи администратора и попытки входа для идентификаторов developer_api1 / customer1usx[@]gmail.com и шаблона dev_xxxxxx / dev_xxxxxx[@]gmail.com, а также любые запросы с параметрами веб-шелла developer_api1_fm или developer_api1_eval. Поскольку правило основано на специфических значениях атакующего, риск ложных срабатываний для сайтов, использующих эти плагины, практически отсутствует: ни один легитимный администратор не создаёт пользователя с именем developer_api1 и почтой customer1usx@gmail.com. Важно понимать, что это смягчение, а не очистка. Оно не даёт автоматической эксплуатации завершиться на ещё незащищённом сайте, но не удаляет учётную запись злоумышленника или бэкдор, созданные до включения защиты.
Администраторам, использовавшим любой из трёх плагинов, следует немедленно проверить список пользователей на наличие подозрительных учётных записей, особенно соответствующих указанным шаблонам, а также проверить установленные плагины на наличие незнакомых модулей. Если атака уже произошла, необходимо удалить созданного администратора, деактивировать и удалить вредоносный плагин, а также сменить все пароли и ключи API. Атаки на цепочку поставок через компрометацию CDN становятся всё более распространённым вектором, и этот инцидент - очередное напоминание о том, что даже полностью обновлённое программное обеспечение может оказаться под угрозой, если поставщик услуг сам становится жертвой взлома.
Индикаторы компрометации
IPv4
- 84.201.6.54
Domains
- tidio.cc
URLs
- a.omappapi.com/app/js/api.min.js
- a.opmnstr.com/app/js/api.min.js
- a.optnmstr.com/app/js/api.min.js
- a.trstplse.com/app/js/api.min.js
- clientcdn.pushengage.com/sdks/pushengage-web-sdk.js
Emails
- customer1usx@gmail.com
- dev_xxxxxx@gmail.com