Темы



Когда сканеры пропускают атаку: как Cloudflare Client-Side Security защищает интернет-магазины

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

Именно эту слепую зону призвана обнаружить наша модель машинного обучения (ML) для обеспечения безопасности на стороне клиента. В этой статье рассматриваются четыре операции, включающие восемь полезных нагрузок, которые система Page Shield ML обнаружила в «дикой природе». 

Обнаружение этих вредоносных полезных нагрузок происходило в автоматическом режиме; люди проверяли каждую находку только после того, как система помечала ее как подозрительную. Когда впоследствии мы проанализировали эти кампании с помощью инструментов сканирования безопасности, семь из восьми полезных нагрузок полностью отсутствовали на VirusTotal, а URLScan не вынес вредоносного вердикта ни для одной из них. При этом Page Shield ML выявила все восемь в условиях реального трафика.

Например, хотя исследования безопасности описывали более широкое семейство Lnkr еще много лет назад, одна конкретная версия полезной нагрузки индексировалась в URLScan почти два с половиной года со статусом «Без классификации» — в том числе во время прямой проверки в январе 2024 года. Только в данном случае VirusTotal зафиксировал полезную нагрузку раньше: хотя сейчас он помечает скрипт как вредоносный, в публичной истории не указано, когда этот вердикт был присвоен впервые. В то же время Page Shield ML независимо обнаружила те же самые байты прямо на витрине онлайн-ритейлера. В более общем плане хэш может быть известен задолго до того, как стоящий за ним код будет классифицирован как вредоносный. Если ваша защита ждет появления этой метки, вы уже опоздали. Вам необходима система машинного обучения, способная самостоятельно анализировать JavaScript и оценивать его в масштабе.

Действительно, увидеть файл — не значит понять его. Самое сложное заключалось в том, что четыре операции не имели универсальной сигнатуры или общего метода маскировки. Одна из них оставалась в спящем режиме до тех пор, пока устройство, страна, время, источник перехода (referrer) или состояние браузера не совпадали с ожидаемыми параметрами. Другая скрывала партнерский запрос без кликов внутри невидимого iframe. Третьи перехватывали клики, подавляли мониторинг или условно загружали дополнительный код с удаленных серверов. Чтобы обнаружить их, нужно отслеживать взаимодействие всех этих элементов: когда скрипт просыпается, что он скрывает, что перехватывает и что запрашивает дальше. Проверить страницу один раз недостаточно; как показывают эти случаи, такие скрипты созданы для того, чтобы не привлекать внимания до появления подходящей жертвы. Именно поэтому постоянный контроль браузера позволяет отличить реальное обнаружение атаки от ее полной пропуски.

Как мы обнаруживаем и классифицируем JavaScript в больших масштабах

Та же графовая нейронная сеть (GNN), которая зафиксировала четыре упомянутые в статье операции, ранее успешно выявляла вредоносные npm-пакеты и реальные скрипты Magecart для кражи платежных данных. GNN не рассматривает JavaScript как сплошной массив текста; она анализирует код как граф: синтаксическое дерево связывает символы кода и показывает, что и кого вызывает, что злоумышленник пытался скрыть и куда отправляются запросы. Эта структура помогает распознавать подозрительные паттерны при минификации, переименовании и обфускации без опоры на известный URL или сигнатуру байтов. 

Те немногие скрипты, которые GNN относит к категории вредоносных (менее 0,3% всего проанализированного трафика), передаются легковесной большой языковой модели (LLM) на базе Workers AI для получения экспертного мнения в реальном времени. Это дополнительно снижает количество ложноположительных срабатываний, сохраняя при этом высокую полноту обнаружения.

Для масштабного расследования наиболее сложных скриптов мы используем группу передовых моделей, которые называем преподавателями (ансамбль автоматизированных арбитров). Эта группа включает ведущие модели примерно из шести различных семейств, в том числе модели с открытыми весами, работающие на Workers AI. Каждую из них мы запускаем в качестве агента для анализа одного и того же подозрительного скрипта в собственной изолированной независимой сессии. При необходимости агентный доступ к инструментам позволяет им использовать ограниченный интерпретатор JavaScript для разбора небольших фрагментов и выявления скрытого поведения. Вскоре мы расширим этот рабочий процесс с помощью Cloudflare Sandbox для более глубокого анализа в изолированных средах.

Передовые модели иногда расходятся в оценках, особенно при анализе сложнейших скриптов. Мы рассматриваем эти разногласия как полезный сигнал, а не как шум. Каждая оценка становится голосом, вес которого определяется баллом модели в рейтинге Artificial Analysis Intelligence Index, что формирует распределение вероятностей по четырем категориям: безопасный, кража платежных данных (magecart), другое вредоносное ПО и майнинг криптовалюты. Таким образом, специалистам по проверке нужно изучать только те скрипты, которые помечены как вредоносные или не имеют четкого большинства в две трети голосов. Затем мы возвращаем эти распределения оценок в процесс обучения GNN, помогая ей различать все более тонкие нюансы. Этот цикл обратной связи пока частично ручной, хотя мы уже начинаем его автоматизировать.

Четыре обнаруженные нами вредоносные JavaScript-операции

Эти четыре операции выполняют совершенно разные задачи: от хищения комиссионных до подделки аналитики по покупателям, за привлечение которых магазин уже заплатил. Кража комиссии не похожа на перехват данных кредитной карты; точно так же подмена поисковой выдачи отличается от кражи пароля. Если модель машинного обучения знает только один из этих трюков, она пропустит остальные. Поэтому наша система Page Shield ML должна отслеживать любые проявления вредоносного поведения. 

Теперь давайте подробнее рассмотрим каждую из операций и принцип ее работы.

Операция

Влияние на клиентов

Что делает скрипт

1) Перехватчик партнерских комиссий в нерабочее время

Перехватывает партнерские вознаграждения

Ограничения по мобильным устройствам и времени; динамический мониторинг страниц; перехват кликов; многодневный период затишья

2) Бескликовая партнерская кража

Похищает партнерские комиссии без кликов пользователя

Внеэкранный iframe; автоклики по скрытой ссылке в качестве резервного варианта; запросы проверки IP и временные ограничения; ежечасная ротация партнеров

3) Старый саботажник поиска, ставший бэкдором интернет-магазина

Отслеживает пользователей и открывает бэкдор для произвольного выполнения удаленного JavaScript

Блокировка старых ключевых слов; отключение через localStorage; телеметрия; загрузка удаленного кода

4) Клоакер для платного мобильного трафика

Скрывает магазин от мобильных посетителей по рекламным кампаниям, пытается подменять рекламу и аналитику, а также прячет службу поддержки

Фильтры по хосту, области просмотра и UTM-меткам; список из 325 подстрок IP-адресов; отключает 9 инструментов мониторинга/аналитики; трекинговые маяки нулевого пикселя

Операция 1: Перехватчик партнерских комиссий в нерабочее время

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

Убытки магазина

Магазин может выплатить незаслуженную комиссию аккаунту, который не приводил покупателя. Хуже того, если привлечение было совершено добросовестным партнером, принудительный запрос может исказить данные атрибуции, лишив партнера, выполнившего реальную работу, заслуженного кредита и потенциальной выплаты. Ущерб может выйти за рамки одной комиссии: партнеры, потерявшие доверие к системе атрибуции, могут также перестать доверять самому ритейлеру.

Цепочка атаки

Qualified mobile visitor → intercepted product tap → script-selected page opens in new tab + original tab follows attacker’s affiliate route

BLOG-3372 2.png

Как атака оставалась скрытой

Мы обнаружили пять родственных сборки скрипта: две активные и три приостановленные на момент захвата. Каждый активный вариант использует собственный набор условий перед тем, как начать действие: проверяются такие параметры, как тип устройства посетителя и местное время, факт недавнего срабатывания этого трюка, появление кнопки товара и реальный клик по ней. Этот лабиринт правил позволяет скрывать вредоносное поведение во время краткого автоматизированного визита, если специфические условия конкретного варианта не выполнены. Активные скрипты используют MutationObserver (API JavaScript) для отслеживания плиток товаров и кнопок, которые динамически появляются после первичной загрузки страницы. Это позволяет им перехватывать клики по элементам, загружающимся с задержкой, в то время как сканер, загрузивший HTML один раз и остановившийся на этом, может полностью упустить путь перенаправления.

В активных поздних вариантах скрипт перехватывает подходящий под условия клик и записывает трехдневный период затишья в localStorage (оставаясь неактивным на этом устройстве в течение нескольких дней). Затем он выполняет маневр с двумя вкладками: открывает выбранную злоумышленником страницу товара в новой вкладке, чтобы удерживать внимание покупателя, в то время как исходная вкладка совершает быстрый и незаметный переход по партнерской ссылке злоумышленника и обратно в магазин, чтобы внедрить в фоновом режиме cookie-файл атрибуции злоумышленника. Маскировка консоли и самозащитные проверки исходного кода усложняют проверку, а периоды затишья и жесткие временные рамки ограничивают частоту появления вредоносного сценария во время обычных покупок.

Следующий очищенный фрагмент демонстрирует, как полезная нагрузка перехватывает динамические плитки товаров и выполняет обходной маневр с двумя вкладками. Для улучшения читаемости мы упростили идентификаторы, переформатировали код и нейтрализовали целевые URL-адреса.

// Watch for late-rendering product elements and hook clicks
new MutationObserver((_, observer) => {
  const tile = document.querySelector(TARGET_SELECTOR);
  if (!tile) return;
  observer.disconnect();

  tile.addEventListener("click", (e) => {
    // Bail out if cooldown is still active on this device
    const stored = JSON.parse(localStorage.getItem(STORAGE_KEY) || "null");
    if (stored && stored.expires > Date.now()) return;

    e.preventDefault();
    e.stopPropagation();
    localStorage.setItem(
      STORAGE_KEY,
      JSON.stringify({ value: "tracked", expires: Date.now() + COOLDOWN_MS }),
    );

    // Keep shopper engaged in new tab...
    window.open(target.link, "_blank");

    // ... while routing original tab through the attacker's affiliate link
    setTimeout(() => {
      window.location.href = target.redirectUrl;
    }, 200);
  }); // Note: some variants added { once: true } to detach after the first tap
}).observe(document.body, { childList: true, subtree: true });

Приостановленные сборки показали, как кампания может уйти в тень без удаления самого скрипта. Их встроенная конфигурация содержала status: "paused", поэтому они прекращали работу до установки обработчиков кликов. Эти приостановленные скрипты имели собственные конфигурации периода затишья для каждого покупателя (3, 4 и 5 дней). Один из приостановленных скриптов даже содержал комментарий в истории версий, прямо указывающий на то, что кампания была приостановлена после Черной пятницы.

Для первоначальной доставки посетителям операция использовала цепочку маркетинговых поставок сайта: сторонние скрипты и менеджеры тегов, внедренные интернет-магазинами для отслеживания рекламных кампаний и аналитики. Один из подтвержденных путей доставки проходил через два вполне обычных менеджера тегов: Google Tag Manager → другой менеджер тегов → вредоносный скрипт. Именно так полезная нагрузка попадала в браузер, что, однако, не доказывает факт компрометации самих менеджеров тегов.

Злоумышленник даже замаскировал домен, на котором размещался скрипт, чтобы успешно проходить быструю маркетинговую проверку. Один из хостов доставки скрывался на виду: adtargett[.]com отличался всего одной буквой «t» от adtarget[.]com, рекламного домена, зарегистрированного в 1998 году. Похожий домен был зарегистрирован в 2025 году, и, как показала наша проверка, его главная страница представлялась как «Adtarget.com — Performance Marketing Agency». Это таймсквотинг (typosquatting): имитируя реальное рекламное агентство, хост сливался с рутинными маркетинговыми тегами и незаметно доставлял вредоносную полезную нагрузку, которая перехватывала клики покупателей и перенаправляла их по партнерским ссылкам для выплат.

Операция 2: Бескликовая партнерская кража

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

Убытки магазина

Для пострадавшего туристического бизнеса эта атака способна исказить экономику привлечения клиентов: легитимное бронирование или покупка могут быть приписаны незаслуженному партнерскому аккаунту. Код подтверждает наличие скрытых автоматизированных партнерских запросов, однако осталось ли какое-либо конкретное обращение незамеченным на практике с точки зрения завершенной атрибуции, начисления средств на аккаунт или выплаты комиссии, остается неизвестным.

Цепочка атаки

Time-gated browser → covert affiliate request (off-screen iframe) → 1-hour throttle cookie → when blocked, automated hidden-link click fallback

BLOG-3372 3.png

Как атака оставалась скрытой

Скрипт скрывает партнерский запрос с помощью двух уровней: выборочного выполнения (предполетный сетевой фильтр и почасовое расписание) и незаметной доставки (внеэкранный iframe). Первый уровень примечателен тем, что его географические метки не связаны с реальным положением дел: выбор не определяется ни местоположением покупателя, ни локацией магазина.

Сначала скрипт обращается к общедоступному сервису геолокации по IP, но игнорирует все возвращаемые им данные, включая страну покупателя. Нам не удалось выяснить, зачем ему требовался успешный ответ при полном игнорировании полученной информации; возможно, это делалось для того, чтобы запутать исследователей, или являлось пережитком более ранней версии. Интересно, что в случае сбоя запроса геолокации скрипт молча прекращает работу: цепочка промисов завершается вызовом .catch (() => {}). Хотя злой умысел не доказан, такое поведение при сбое (fail-closed) может помогать скрипту избегать изолированных сред с ограничениями сети.

Затем, вместо использования полученных данных геолокации, полезная нагрузка содержит три объекта конфигурации TradeDoubler (сети партнерского маркетинга), озаглавленные {AU, US и UK}. Эти блоки настроек встроены в код, и каждый из них содержит партнерский URL-адрес, а также время начала и окончания. Скрипт вычисляет время Asia/Kolkata с помощью JavaScript, проверяет заданные временные окна, а затем применяет фиксированные правила четных и нечетных часов для выбора одного из трех вариантов либо пропускает партнерский запрос для данного запуска. Выбор носит детерминированный характер. 

В совокупности расписание и проверки состояния браузера создают избирательное выполнение на основе временных ограничений, представляющее собой разновидность клоакинга. Когда эти условия не совпадают, партнерская активность остается в спящем режиме, поэтому единичная проверка может ее не заметить.

После выбора конфигурации скрипт записывает локальный файл cookie с именем affiliateClicked_ в качестве часового ограничения на повторные попытки, чтобы не срабатывать для этого региона сразу же (это клиентское ограничение для снижения шума, а не cookie-файл атрибуции партнерской сети). Затем он загружает этот партнерский URL-адрес во внеэкранном iframe с подавленным заголовком referrer. Ифрейм является основным путем доставки, но он снабжен агрессивным резервным механизмом: если ифрейм выдает ошибку или не завершает загрузку через одну-две секунды, скрипт создает скрытую ссылку () без атрибута target и программно кликает по ней, что может привести к переходу во вкладке пользователя. Для ничего не подозревающего покупателя все выглядит нормально: он никогда не видит рекламу, ему не нужно никуда кликать, и он может закрыть вкладку так, будто ничего не произошло.

Что касается обфускации скрипта, она проста, но эффективна: даже имена свойств собираются по одному символу за раз. Следующий очищенный фрагмент демонстрирует создание полезной нагрузкой невидимого внеэкранного iframe. Ключевые идентификаторы были переименованы, а код переформатирован для удобства чтения. Целевой адрес удален.

function loadAttribution(target) {
  const frame = document['c'+'r'+'e'+'a'+'t'+'e'+'E'+'l'+'e'+'m'+'e'+'n'+'t'](
    'i'+'f'+'r'+'a'+'m'+'e'
  );
  frame['s'+'r'+'c'] = target;
  frame['r'+'e'+'f'+'e'+'r'+'r'+'e'+'r'+'P'+'o'+'l'+'i'+'c'+'y'] =
    'n'+'o'+'-'+'r'+'e'+'f'+'e'+'r'+'r'+'e'+'r';
  frame['s'+'t'+'y'+'l'+'e']['c'+'s'+'s'+'T'+'e'+'x'+'t'] =
    'w'+'i'+'d'+'t'+'h'+':'+'1'+'p'+'x'+';'+'h'+'e'+'i'+'g'+'h'+'t'+':'+'1'+'p'+'x'+';'+
    'p'+'o'+'s'+'i'+'t'+'i'+'o'+'n'+':'+'a'+'b'+'s'+'o'+'l'+'u'+'t'+'e'+';'+
    'l'+'e'+'f'+'t'+':'+'-'+'9'+'9'+'9'+'9'+'p'+'x'+';'+
    'v'+'i'+'s'+'i'+'b'+'i'+'l'+'i'+'t'+'y'+':'+'h'+'i'+'d'+'d'+'e'+'n';
  document['b'+'o'+'d'+'y']['a'+'p'+'p'+'e'+'n'+'d'+'C'+'h'+'i'+'l'+'d'](frame);
}

Операция 3: Старый саботажник поиска, ставший бэкдором интернет-магазина

Много лет назад семейство вредоносного ПО Lnkr попало в новостные заголовки благодаря маскировке внутри сомнительных расширений браузера, перехвату поисковых запросов Google и Bing с целью подмены результатов и присвоения рекламных доходов. Теперь злоумышленники перепрофилировали эту кодовую базу для внедрения бэкдора на сайт интернет-магазина.

Поскольку скрипт работал в магазине, а не в поисковой системе, его старые трюки с перенаправлением оставались в спящем состоянии. На этот раз скрипт использовался для отправки телеметрии злоумышленнику. Что еще опаснее, он предоставил злоумышленнику удаленный шлюз для произвольной загрузки и запуска нового JavaScript в браузерах покупателей в любой момент без изменения хотя бы одного файла на сервере. Он даже сохранил старый трюк времен работы в качестве расширения: самоотключение при вводе в поисковую строку Google таких слов, как «virus» или «popup». Снаружи магазин продолжал осуществлять продажи без малейших признаков каких-либо проблем.

Убытки магазина

Магазин потерял контроль над тем, какой код выполняется в браузерах его клиентов. Злоумышленники тайно отслеживали сеансы посетителей и имели прямой бэкдор для принудительной загрузки и выполнения любого JavaScript на витрине в любой момент времени.

Цепочка атаки

HTML-referenced script → analyst evasion gates → parallel host-gated branches (dormant search vs. live backdoor) → arbitrary remote JavaScript execution

BLOG-3372 4.png

Как атака оставалась скрытой

В отличие от кампаний, доставляемых через менеджеры тегов, этот скрипт был встроен непосредственно в HTML код продавца. Нам не удалось определить точный вектор первоначального проникновения; на практике прямые внедрения в HTML обычно происходят через скомпрометированные учетные записи администратора магазина, несанкционированное редактирование шаблонов или зараженные сторонние темы и плагины.

Под капотом скрипт представляет собой модульный набор инструментов, содержащий как активный, так и спящий код. Его старые модули (прозрачные клик-оверлеи, перехватчики поисковых запросов, средства перезаписи ссылок в магазинах расширений и перенаправления для таймсквотинговых доменов вроде buking[.]com вместо booking[.]com) активируются только на определенных целевых сайтах, поэтому на этой витрине они оставались отключенными. Несколько встроенных доменов (sugabit[.]net, votetoda[.]com, cdnpps[.]us и эндпоинт телеметрии hanstrackr[.]com) находились внутри этих отключенных модулей.

В самом магазине активные ветки были сосредоточены на обходе защиты, телеметрии и удаленном управлении:

  • Имитация бездействия перед исследователями безопасности. Трюк для обхода защиты, унаследованный со времен браузерных расширений: скрипт отслеживал поисковые запросы и параметры URL на наличие характерных терминов рекламного ПО. Ввод одного ключевого слова безопасности приостанавливал работу скрипта для данного визита. Ввод двух и более ключевых слов приводил к записи постоянной отметки об отказе в localStorage, навсегда отключая скрипт на компьютере этого аналитика, чтобы повторные тесты ничего не обнаруживали. Хотя изначально эта проверка создавалась для обхода аналитиков в поисковых системах, насколько нам удалось выяснить, она была жестко запрограммирована именно на URL-адреса поиска Google и оставалась неактивной на витрине интернет-магазина.
  • Динамическое выполнение удаленного кода. Скрипту не требовалось изменять саму витрину для изменения своего поведения. Хотя зашитые в код имена доменов (scrprime[.]com, youronlinesearches[.]com, jullyambery[.]net) оставались неизменными по сравнению со старыми образцами, содержимое, возвращаемое этими эндпоинтами, полностью определялось злоумышленником. Скрипт мог передавать на сервер телеметрию посетителей, запрашивать у этих серверов новые инструкции и загружать свежий JavaScript прямо в браузер покупателя. Фактически это давало злоумышленникам действующий бэкдор для выполнения произвольного кода на витрине. Нам не удалось определить, какие именно полезные нагрузки второго этапа доставлялись на практике.

В целом, статический снимок сайта демонстрировал лишь обычную витрину, в то время как лежащие в основе проверки состояния, средства защиты от анализа и ветки удаленной загрузки выдавали наличие бэкдора.

Операция 4: Клоакер для платного мобильного трафика

Магазин уже заплатил за привлечение этого посетителя из мобильной рекламы или маркетинговой кампании. Вредоносный скрипт пропускает этот визит, а затем перекрывает продавцу всю видимость. Аналитика отключается, чат техподдержки исчезает, а сторонний наблюдатель начинает записывать телеметрию по именно той сессии, за которую магазин только что заплатил. 

За кулисами полезная нагрузка отказывается работать до тех пор, пока визит не совпадет со сложным набором условий: конкретная целевая витрина, узкий экран мобильного устройства и рекламная метка в течение первых двух страниц сессии. Она остается неактивной на ноутбуках, корпоративных сетях, у облачных провайдеров и через VPN, поэтому инженеры, наиболее склонные к отладке страницы, никогда не видят ее срабатывания. Скрипт также бездействует в определенных городах и регионах США, опираясь на созданный вручную черный список из 325 строк IP-адресов для защиты от автоматических сканеров и аналитиков безопасности. Только после этого скрипт пытается отключить мониторинг магазина, подменить рекламу и идентификаторы аналитики, а также связаться с командным сервером. Повторная проверка с неподходящего устройства или из неподходящей сети никогда не вызовет его активацию. При этом магазин продолжает продавать.

Убытки магазина

Для ритейлера, работающего по модели direct-to-consumer, вредоносное ПО целенаправленно атаковало ценный трафик, который магазин приобрел с помощью платного поиска и маркетинговых кампаний (ppc, cpc, sms, paid). Эти клиенты по-прежнему могли совершать покупки. Тем не менее, магазин столкнулся с тремя явными угрозами: подменой рекламной атрибуции и выплатами незаслуженных комиссий издателям, потерей критически важной аналитики сеансов по девяти инструментам наблюдения, а также блокировкой чата помощи и контактной формы (что мешало покупателям задавать вопросы или сообщать об аномалиях). Динамический анализ в изолированной среде браузера подтвердил, что подменный скрипт аналитики загружался и отправлял трекинговый маяк (невидимый сетевой запрос для логирования активности посетителей), однако осталось ли незафиксированным на практике успешное перехватывание злоумышленником телеметрии сеанса или перенаправление рекламных доходов, остается недоказанным.

Цепочка атаки

Campaign-tagged mobile arrival → multi-tier cloaking & network gates → monitoring sabotaged → advertising, analytics, and support controls rewritten 

BLOG-3372 5.png

Как атака оставалась скрытой

Чтобы слиться с цепочкой маркетинговых поставок магазина, злоумышленник доставил полезную нагрузку с домена sdk-amazonaws[.]com, похожего домена, зарегистрированного в 2024 году и не имеющего никакого отношения к официальному домену Amazon Web Services (amazonaws.com, зарегистрированному в 2005 году). Для усиления обмана злоумышленник добавил к домену префикс в виде поддомена, также имитирующего популярную платформу для маркетинга электронной коммерции. Этот многоуровневый таймсквотинг с использованием доверенных брендов создал убедительную маскировку, призванную обойти быстрые проверки тегов. Ни Amazon Web Services, ни имитируемая маркетинговая платформа не были причастны к атаке или скомпрометированы.

После загрузки в браузер скрипт выполнял исключительно плотную цепочку фильтров маскировки перед запуском основной полезной нагрузки:

  • Целевой хост и контекст просмотра. Скрипт проверял, соответствует ли window.location.hostname конкретному хосту продавца, для работы на котором он создавался (в противном случае немедленно прекращая работу), удостоверялся, что текущее окно является корневым (а не внедренным iframe), и проверял, что путь не содержит /challenge. Он также проверял отсутствие в браузере файлов cookie с маркерами отслеживания (_cart_dr и logoalt).
  • Фильтрация по устройству и рекламной кампании. Ширина области просмотра посетителя должна была быть меньше 477 пикселей (портативный смартфон). Кроме того, посетитель должен был перейти по кампании типа first-touch (первичный источник перехода посетителя), помеченной одной из шести специфических UTM-меток (Urchin Tracking Module, стандартные теги URL для отслеживания маркетинговых кампаний): ppc, cpc, sms, paid, flow или campaign. Это также должен был быть первый или второй просмотр страницы за сеанс. Как ни странно, хотя в коде присутствовал номинальный путь без UTM, он требовал, чтобы количество просмотров страниц за сеанс было одновременно больше -1 и меньше -2 (математическая невозможность, делающая эту ветку полностью недоступной). Это может быть еще одним методом отвлечения внимания или оставшимся фрагментом старого кода.
  • «Случайный» шлюз, который срабатывал всегда. В коде присутствовало подобие вероятностного регулятора (Math.random() <= threshold), призванного создавать видимость периодического выполнения. Однако, когда мы решили деобфусцированную арифметику, пороговое значение свелось ровно к 1. Поскольку метод JavaScript Math.random() всегда возвращает значение строго меньше 1, этот шлюз всегда возвращает true. Как и в случае с недостижимой веткой без кампании, это условие на самом деле ничего не решает. Это может быть оставшийся регулятор или намеренная маскировка для тех, кто читает обфусцированную математику. В любом случае, перехваченный полезный нагрузка никогда не использовала его для пропуска квалифицированного посетителя.
  • Сторонняя IP-аналитика. Скрипт запрашивал внешний сторонний API IP-аналитики, используя встроенный ключ. Для этого требовалось мобильное потребительское соединение из США, причем скрипт немедленно прерывал работу, если в ответе содержался признак бизнес-сети, хостинг-провайдера, облачного сервиса, богона, выходного узла Tor, VPN, прокси, ретранслятора или общего индикатора угрозы.
  • Географические исключения. Полезная нагрузка не активировалась для посетителей из определенных регионов (US-NY, US-CA и US-NHDD) или из городов Сан-Франциско, Плимут, Комптон, Хопкинтон и Лафайет.
  • Ловушка по подстроке IP из 325 записей. Скрипт сверял IP посетителя со встроенным черным списком, содержащим 325 полных строк IPv4-адресов. После удаления дубликатов они представляли 313 уникальных адресов в 249 различных префиксах из трех октетов. Вместо выполнения структурированного сопоставления подсетей CIDR (Classless Inter-Domain Routing), автор просто отбросил последний октет из IPv4-адреса посетителя и выполнил поиск по исходной подстроке: !denylistString.includes(visitorPrefix).

В упрощенном псевдокоде многоуровневая первичная воронка активации выглядит следующим образом:

// 1. Context, device, and campaign gates
let eligible = isTopWindow && host === EXPECTED_HOST && !path.includes("/challenge");
eligible &&= !hasCookie("_cart_dr") && !hasCookie("_logo_alt");
eligible &&= viewportWidth < 477 && [1, 2].includes(sessionPage);
eligible &&= ["ppc", "cpc", "sms", "paid", "flow", "campaign"].includes(utmMedium);
eligible &&= Math.random() <= 1; // Apparent random gate always resolves to true

// 2. IP intelligence & geographic gates (fetching external API)
eligible &&= ipInfo.country === "US" && ipInfo.isMobile && !ipInfo.isBusiness;
eligible &&= !ipInfo.isCloud && !ipInfo.isProxy && !ipInfo.isVpn && !ipInfo.isTor && !ipInfo.isThreat;
eligible &&= !["US-NY", "US-CA", "US-NHDD"].includes(ipInfo.region);
eligible &&= !EXCLUDED_CITIES.includes(ipInfo.city);

// 3. 325-entry IP prefix check (raw substring matching)
let clientPrefix = ipInfo.ip.slice(0, ipInfo.ip.lastIndexOf("."));
eligible &&= !DENYLIST_STRING.includes(clientPrefix);

if (!eligible) return; // Cloak passes only for qualifying consumer mobile sessions

Саботаж систем наблюдаемости и перехват идентификаторов:

Только после прохождения всех основных шлюзов скрипт выполнял свою полезную нагрузку:

  • Ослепление инструментов мониторинга. Он выполнял поиск в DOM и удалял теги скриптов для девяти различных сервисов наблюдаемости и аналитики: Lucky Orange, Segment, Optimizely, New Relic, Bugsnag, LogRocket, Hotjar, Microsoft Clarity и контейнера Google Tag Manager магазина (GTM-). В оставшихся встроенных скриптах он заменял строки с упоминаниями этих инструментов на неопределенные фиктивные идентификаторы (hji0), из-за чего вызовы к ним завершались молчаливым сбоем, пытаясь заблокировать отправку отчетов об ошибках и мониторинг магазина.
  • Подавление службы поддержки клиентов. Он внедрял CSS и удалял элементы для скрытия контейнеров чата поддержки и контактной формы, перекрывая клиенту прямую связь со службой поддержки магазина.
  • Замена рекламных и аналитических идентификаторов. Он очищал глобальные переменные Google Ads (google_ad_modifications, adsbygoogle), демонтировал существующие рекламные блоки (ca-pub-) и загружал Google Ads под заменяющим идентификатором издателя (ca-pub-). Затем он внедрял новый скрипт сеансовой записи Microsoft Clarity, настроенный с поддельным заменяющим идентификатором проекта.

Более простые независимые маяки и 600-дневный маркер:

В резком контрасте со сложной первичной маскировкой, полезная нагрузка также содержала вторичные ветки маяков (автономные процедуры, которые незаметно отправляют запрос на внешний сервер для подтверждения визита), которые полностью обходили область просмотра, имя хоста, кампанию, географию и IP-шлюзы. Если посетитель находился на второй или последующей странице, скрипт записывал постоянный файл cookie (_cart_dr=1) со сроком действия ровно 600 дней (51 840 000 000 миллисекунд) и отправлял невидимый запрос изображения размером в один пиксель на удаленную конечную точку телеметрии на maper[.]info (маяк отслеживания, используемый для регистрации того, что браузер достиг этого шага).

Отдельная ветка проверяла наличие альтернативного маркера (_logo_alt), который инициировал бы второй маяк телеметрии .png (файл cookie, который этот скрипт искал, но никогда не записывал самостоятельно; вероятно, установленный сопутствующим скриптом). Это давало злоумышленнику простой постоянный счетчик посещений для регистрации базового трафика всех посетителей (IP и User-Agent регистрировались на конечной точке) по всему магазину, в то время как их высокорисковые рутины перехвата рекламы строго скрывались за мобильной маскировкой (высокоценные платные переходы). Это показывает, почему анализ только одного видимого эффекта не раскрывает всего масштаба многоцелевой полезной нагрузки.

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

Мы публикуем эти индикаторы, чтобы помочь командам безопасности и исследователям обнаруживать и отслеживать эти кампании в собственных средах. Все индикаторы получены непосредственно из перехваченных полезных нагрузок и их сетевых соединений. Указанные URL-адреса обезврежены. Некоторые индикаторы были скрыты или обобщены, поскольку их публикация может непреднамеренно раскрыть личности пострадавших организаций. Указанные домены отражают инфраструктуру, замеченную в участии в цепочке доставки, перенаправления или телеметрии во время этих атак; включение в список не означает, что общий сервис или хостинг-провайдер является исключительно вредоносным.

Операция

Индикатор

Тип и роль

1) Внеурочный перехватчик партнерских комиссионных

adtargett[.]com

Тайпсквоттинговый домен доставки скриптов и партнерского перенаправления

1) Внеурочный перехватчик партнерских комиссионных

gdataroute[.]com

Служба коротких ссылок партнерского перенаправления, замеченная в цепочке атаки

3) Старый поисковый саботажник, теперь бэкдор витрины

scrprime[.]com

Домен доставки скрипта браузерного хиджакера

3) Старый поисковый саботажник, теперь бэкдор витрины

searchvalidation[.]com

Домен перехвата поиска и перенаправления трафика

3) Старый поисковый саботажник, теперь бэкдор витрины

sugabit[.]net

Домен принудительного перенаправления поиска

3) Старый поисковый саботажник, теперь бэкдор витрины

youronlinesearches[.]com

Домен условной доставки удаленных скриптов

3) Старый поисковый саботажник, теперь бэкдор витрины

hublosk[.]com

Домен доставки удаленных скриптов

3) Старый поисковый саботажник, теперь бэкдор витрины

jullyambery[.]net

Домен удаленного API JavaScript и команд

3) Старый поисковый саботажник, теперь бэкдор витрины

votetoda[.]com

Домен доставки внедренной полезной нагрузки

3) Старый поисковый саботажник, теперь бэкдор витрины

hanstrackr[.]com

Домен скрытой телеметрии посетителей

3) Старый поисковый саботажник, теперь бэкдор витрины

adrs[.]me

Служба перенаправления тайпсквоттингового трафика, замеченная в цепочке атаки

3) Старый поисковый саботажник, теперь бэкдор витрины

youradexchange[.]com

Служба перенаправления для монетизации, замеченная в цепочке атаки

3) Старый поисковый саботажник, теперь бэкдор витрины

cdnpps[.]us

Домен доставки внедренного рекламного фрейма

4) Клоакер для платного мобильного трафика

sdk-amazonaws[.]com

Похожий домен доставки скриптов, злоупотребляющий доверием к бренду

4) Клоакер для платного мобильного трафика

maper[.]info

Домен условного маяка телеметрии посетителей

Четыре урока для защитников

В совокупности эти операции рассказывают единую эскалирующую историю: злоумышленники меняли цели, пути доставки и маскировку, но браузер по-прежнему был обязан выполнять их логику. Выделяются четыре урока.

Поведение важнее сигнатур. Эти операции преследовали различные формы монетизации и манипуляций, но каждая полезная нагрузка все равно должна была действовать в браузере: отслеживать события, проверять состояние, изменять страницу, планировать работу, выполнять сетевые запросы или загружать следующий этап. Именно это ищет структурный анализ: логику, которую враждебная полезная нагрузка должна нести в себе даже при изменении URL-адресов, сигнатур и целей.

Выборочное выполнение является частью атаки, а не сноской. Устройство, время, география, источник перехода, сеанс, сеть и задержки могут обмануть сканер, который посещает страницу один раз и делает статический снимок. Непрерывная видимость имеет значение, поскольку атака может проявиться только в одном браузере, в определенном состоянии и в определенный момент.

Обфускация увеличила стоимость анализа, но в данных случаях она не предотвратила обнаружение. Самозащитные циклы, подавление консоли, ловушки для отладчиков, переставленные таблицы строк и мертвые ветки усложнили анализ. Page Shield ML все равно выявила все четыре операции вопреки этим барьерам. Быстрые внутренние модели обнаруживают подозрительный код в больших масштабах, в то время как передовые модели исследуют самые сложные случаи. Их разногласия подчеркивают наиболее изощренную обфускацию и логику, помогая сузить область поиска.

Контекст дополняет картину. Код, который выглядит обычным изолированно, может раскрыть свою вредоносную роль, как только защитники свяжут статический анализ с динамическим контекстом: как он прибыл, какое состояние браузера его активировало, какие соединения он открыл и что он на самом деле делал во время выполнения.

Непрерывная видимость клиентского выполнения

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

Cloudflare Client-Side Security обеспечивает такую видимость для всех тарифных планов. Вы можете включить непрерывный мониторинг скриптов в настройках безопасности для отслеживания собственных и сторонних скриптов на вашей витрине, в то время как автоматическое обнаружение вредоносных скриптов и оповещения доступны в рамках Client-Side Security Advanced. Вы можете просматривать активность скриптов и управлять обнаружениями непосредственно в панели управления Cloudflare.

© Cloudflare Blog