Third Party JavaScript Management Cheat Sheet¶
Введение¶
Теги, также известные как маркетинговые теги, аналитические теги и т.п., представляют собой небольшие фрагменты JavaScript-кода на веб-странице. Они также могут быть HTML-элементами изображений, когда JavaScript отключён. Цель их использования — сбор данных о действиях веб-пользователей и контексте просмотра для использования владельцем сайта в маркетинговых целях.
Теги JavaScript сторонних поставщиков (далее — теги) можно разделить на два типа:
- Теги пользовательского интерфейса.
- Аналитические теги.
Теги пользовательского интерфейса должны выполняться на стороне клиента, поскольку они изменяют DOM: отображают диалоговые окна, изображения, изменяют текст и т.п.
Аналитические теги отправляют информацию обратно в маркетинговую базу данных: сведения о только что выполненном действии пользователя, метаданные браузера, геолокацию, метаданные страницы и т.д. Смысл аналитических тегов — передача данных из DOM браузера пользователя поставщику для проведения маркетингового анализа. Эти данные могут быть любыми, доступными в DOM. Они используются для анализа навигации пользователей и clickstream, идентификации пользователей с целью определения контента для отображения и т.д., а также для различных функций маркетингового анализа.
Термин хост обозначает исходный сайт, на который заходит пользователь (например, магазин или новостной сайт), который содержит, получает и выполняет теги JavaScript сторонних поставщиков для маркетингового анализа действий пользователей.
Основные риски¶
Наибольшим единичным риском является компрометация сервера стороннего JavaScript-кода с последующим внедрением вредоносного JavaScript в оригинальный тег. Подобное происходило в 2018 году и, вероятно, ранее.
Вызов стороннего JS-кода в веб-приложении требует учёта трёх рисков в особенности:
- Потеря контроля над изменениями клиентского приложения,
- Выполнение произвольного кода на клиентских системах,
- Раскрытие или утечка конфиденциальной информации третьим сторонам.
Риск 1: Потеря контроля над изменениями клиентского приложения¶
Этот риск возникает из-за того, что, как правило, нет никакой гарантии того, что код, размещённый у третьей стороны, останется таким же, каким его видели разработчики и тестировщики: в код третьей стороны в любое время могут быть добавлены новые функции, что потенциально может нарушить работу интерфейса или потоков данных и поставить под угрозу доступность вашего приложения для пользователей/клиентов.
Типичные меры защиты включают, но не ограничиваются: хранение зеркальных копий скриптов на собственных серверах (для предотвращения изменений со стороны третьих лиц), subresource integrity (для обеспечения перехвата на уровне браузера) и безопасная передача стороннего кода (для предотвращения изменений при передаче). Подробнее см. ниже.
Риск 2: Выполнение произвольного кода на клиентских системах¶
Этот риск возникает из-за того, что сторонний JavaScript-код редко проверяется вызывающей стороной перед интеграцией на сайт/в приложение. Когда клиент обращается к хостинговому сайту/приложению, этот сторонний код выполняется, тем самым предоставляя третьей стороне ровно те же привилегии, что были предоставлены пользователю (аналогично XSS-атакам).
Любое тестирование, проведённое до выхода в продакшен, частично теряет свою актуальность, включая AST testing (IAST, RAST, SAST, DAST и т.д.).
Хотя широко принято считать, что вероятность преднамеренного внедрения вредоносного кода третьей стороной невелика, всё же существуют случаи злонамеренного внедрения в сторонний код после компрометации серверов организации (пример: Yahoo, январь 2014 г.).
Этот риск следует оценивать в особенности тогда, когда третья сторона не предоставляет никакой документации, подтверждающей применение более строгих мер безопасности, чем у самой вызывающей организации, или хотя бы эквивалентных. Ещё один пример: домен, на котором размещён сторонний JavaScript, истекает, потому что компания, его поддерживающая, обанкротилась, или разработчики забросили проект. Тогда злоумышленник может зарегистрировать домен повторно и опубликовать вредоносный код.
Типичные меры защиты включают, но не ограничиваются:
- Хранение зеркальных копий скриптов на собственных серверах (для предотвращения изменений со стороны третьих лиц),
- Sub-resource integrity (для обеспечения перехвата на уровне браузера),
- Безопасная передача стороннего кода (для предотвращения изменений при передаче) и различные виды песочницы. Подробнее см. ниже.
- ...
Риск 3: Раскрытие конфиденциальной информации третьим сторонам¶
Когда сторонний скрипт вызывается на сайте/в приложении, браузер напрямую обращается к серверам третьей стороны. По умолчанию запрос включает все стандартные HTTP-заголовки. Помимо исходного IP-адреса браузера, третья сторона получает и другие данные: реферер (в запросах не по HTTPS) и все cookie, ранее установленные третьей стороной, например при посещении сайта другой организации, который также вызывает скрипт третьей стороны.
Во многих случаях это предоставляет третьей стороне первичный доступ к информации о пользователях/клиентах организации. Кроме того, если третья сторона предоставляет скрипт другим организациям, она также собирает вторичные данные от всех этих организаций, таким образом зная не только кто является посетителями данной организации, но и с какими другими организациями они взаимодействуют.
Типичный случай — текущая ситуация с крупными новостными сайтами, которые вызывают сторонний код (как правило, для рекламных движков, статистики и JavaScript API): любой пользователь, посещающий эти сайты, также сообщает третьим сторонам о своём визите. Во многих случаях третья сторона также узнаёт, на какие конкретно новостные статьи нажимает каждый отдельный пользователь (утечка происходит через поле HTTP referrer), и таким образом может составить более детальные профили личности.
Типичные меры защиты включают, но не ограничиваются: хранение зеркальных копий скриптов на собственных серверах (для предотвращения утечки HTTP-запросов третьим сторонам). Пользователи могут снизить степень профилирования, случайно нажимая ссылки на сайтах с утечками (например, новостных) для снижения эффективности профилирования. Подробнее см. ниже.
Архитектуры развёртывания стороннего JavaScript¶
Существует три основных механизма развёртывания тегов. Эти механизмы могут комбинироваться между собой.
JavaScript поставщика непосредственно на странице¶
В этом случае поставщик предоставляет хосту JavaScript-код, а хост размещает его на своей странице. Для обеспечения безопасности компания-хост должна проверить код на наличие уязвимостей, таких как XSS-атаки, или вредоносных действий, например отправки конфиденциальных данных из DOM на злоумышленный сайт. Зачастую это затруднено, поскольку JavaScript-код обычно обфусцирован.
<!-- Some host, e.g. foobar.com, HTML code here -->
<html>
<head></head>
<body>
...
<script type="text/javascript">/* 3rd party vendor javascript here */</script>
</body>
</html>
Запрос JavaScript с сервера поставщика¶
В этом случае одна или несколько строк кода на странице хоста запрашивают JavaScript-файл или URL напрямую с сайта поставщика. При создании страницы хоста разработчик включает предоставленные поставщиком строки кода, которые будут запрашивать JavaScript поставщика. При каждом обращении к странице запросы отправляются на сайт поставщика за JavaScript-кодом, который затем выполняется в браузере пользователя.
<!-- Some host, e.g. foobar.com, HTML code here -->`
<html>
<head></head>
<body>
...
<!-- 3rd party vendor javascript -->
<script src="https://analytics.vendor.com/v1.1/script.js"></script>
<!-- /3rd party vendor javascript -->
</body>
</html>
Косвенный запрос к поставщику через менеджер тегов¶
В этом случае одна или несколько строк кода на странице хоста запрашивают JavaScript-файл или URL с сайта-агрегатора тегов или менеджера тегов; не с сайта поставщика JavaScript напрямую. Сайт агрегатора тегов или менеджера тегов возвращает любые сторонние JavaScript-файлы, которые были настроены компанией-хостом для возврата. Каждый запрос файла или URL к менеджеру тегов может возвращать множество других JavaScript-файлов от различных поставщиков.
Фактическое содержимое, возвращаемое агрегатором или менеджером (т.е. конкретные JavaScript-файлы и их функциональность), может динамически изменяться сотрудниками сайта-хоста с помощью графического интерфейса разработки, размещённого на сайте менеджера тегов, с которым могут работать нетехнические пользователи, например сотрудники маркетингового отдела.
Изменения могут быть двух видов:
- Получение другого JavaScript-файла от стороннего поставщика для того же запроса.
- Изменение того, какие данные DOM-объекта считываются, и когда они отправляются поставщику.
Пользовательский интерфейс разработки менеджера тегов генерирует код, реализующий требуемую маркетинговую функциональность: по сути, определяет, какие данные получать из DOM браузера и когда. Менеджер тегов всегда возвращает в браузер контейнерный JavaScript-файл — по существу, набор JavaScript-функций, которые используются кодом, сгенерированным интерфейсом, для реализации требуемой функциональности.
По аналогии с Java-фреймворками, предоставляющими функции и глобальные данные разработчику, контейнерный JavaScript выполняется в браузере и позволяет бизнес-пользователю через интерфейс разработки менеджера тегов задавать высокоуровневую функциональность, не зная JavaScript.
<!-- Some host, e.g. foobar.com, HTML code here -->
<html>
<head></head>
<body>
...
<!-- Tag Manager -->
<script>(function(w, d, s, l, i){
w[l] = w[l] || [];
w[l].push({'tm.start':new Date().getTime(), event:'tm.js'});
var f = d.getElementsByTagName(s)[0],
j = d.createElement(s),
dl = l != 'dataLayer' ? '&l=' + l : '';
j.async=true;
j.src='https://tagmanager.com/tm.js?id=' + i + dl;
f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', 'TM-FOOBARID');</script>
<!-- /Tag Manager -->
</body>
</html>`
Проблемы безопасности при запросе тегов¶
Описанные выше механизмы сложно сделать безопасными, поскольку увидеть код можно только при проксировании запросов или при наличии доступа к GUI с настроенной конфигурацией. JavaScript-код, как правило, обфусцирован, поэтому даже его просмотр обычно не даёт полезной информации. Кроме того, код мгновенно развёртывается, потому что каждый новый запрос страницы из браузера выполняет запросы к агрегатору, который получает JavaScript от стороннего поставщика. Поэтому как только любые JavaScript-файлы будут изменены у поставщика или модифицированы на агрегаторе, следующий их запрос из любого браузера получит изменённый JavaScript. Один из способов управления этим риском — стандарт Subresource Integrity, описанный ниже.
Серверный прямой уровень данных (Server Direct Data Layer)¶
Интерфейс разработки менеджера тегов можно использовать для создания JavaScript, который получает данные из любого места DOM браузера и сохраняет их в любом месте страницы. Это может порождать уязвимости, поскольку через интерфейс можно генерировать код для получения непроверенных данных из DOM (например, параметров URL) и сохранения их в таком месте страницы, где будет выполнен JavaScript.
Лучший способ обеспечить безопасность сгенерированного кода — ограничить его доступ к данным только хост-определённым уровнем данных.
Уровень данных (data layer) может быть:
- DIV-объектом со значениями атрибутов, содержащими маркетинговые данные или данные о поведении пользователей, которые нужны третьей стороне;
- набором JSON-объектов с теми же данными. Каждая переменная или атрибут содержит значение какого-либо элемента DOM или описание действия пользователя. Уровень данных — это полный набор значений, которые нужны всем поставщикам для данной страницы. Уровень данных создаётся разработчиками хоста.
Когда происходят конкретные события, определённые бизнесом, JavaScript-обработчик этого события отправляет значения из уровня данных напрямую на сервер менеджера тегов. Сервер менеджера тегов затем пересылает данные тем третьим сторонам, которым они предназначены. Код обработчика событий создаётся разработчиками хоста с помощью интерфейса разработки менеджера тегов. Код обработчика событий загружается с серверов менеджера тегов при каждой загрузке страницы.
Это безопасный подход, поскольку на браузере ваших пользователей выполняется только ваш JavaScript, и только те данные, которые вы определили, отправляются поставщику.
Это требует взаимодействия между хостом, агрегатором или менеджером тегов и поставщиками.
Разработчики хоста должны согласовать с поставщиком, какой тип данных тому нужен для анализа. Затем программист хоста определяет, какой DOM-элемент будет содержать эти данные.
Разработчики хоста должны согласовать с менеджером тегов или агрегатором протокол передачи данных: URL, параметры, формат и т.д.
Менеджер тегов или агрегатор должен согласовать с поставщиком протокол передачи данных поставщику: URL, параметры, формат и т.д. Есть ли у поставщика API?
Соображения по защите безопасности¶
Серверный прямой уровень данных (Server Direct Data Layer)¶
Механизм серверного прямого уровня данных является хорошим стандартом безопасности для управления, развёртывания и выполнения сторонних JavaScript. Хорошей практикой для страницы хоста является создание уровня данных из DOM-объектов.
Уровень данных может выполнять любую валидацию значений, особенно значений из DOM-объектов, доступных пользователю, например параметров URL и полей ввода, если они требуются для маркетингового анализа.
Пример формулировки для корпоративного стандарта: «Тег JavaScript может обращаться только к значениям в уровне данных хоста. Тег JavaScript никогда не может обращаться к параметру URL».
Разработчик страницы хоста должен согласовать с поставщиками третьих сторон или менеджером тегов, какой атрибут в уровне данных будет содержать то или иное значение, чтобы они могли создать JavaScript для чтения этого значения.
Теги пользовательского интерфейса нельзя сделать безопасными с помощью архитектуры уровня данных, поскольку их функция (или одна из функций) — изменение пользовательского интерфейса на клиенте, а не отправка данных о действиях пользователя.
Аналитические теги можно сделать безопасными с помощью архитектуры уровня данных, поскольку единственное необходимое действие — отправка данных из уровня данных третьей стороне. Выполняется только код первой стороны: сначала для заполнения уровня данных (как правило, при загрузке страницы), затем обработчик событий JavaScript отправляет необходимые данные со страницы в базу данных третьей стороны или менеджеру тегов.
Это также очень масштабируемое решение. Крупные сайты электронной коммерции легко могут иметь сотни тысяч комбинаций URL и параметров, при этом разные наборы URL и параметров включаются в разные маркетинговые кампании. Маркетинговая логика может содержать 30 или 40 различных тегов поставщиков на одной странице.
Например: действия пользователей на страницах о конкретных городах, из конкретных местоположений в конкретные дни должны отправлять элементы уровня данных 1, 2 и 3. Действия пользователей на страницах о других городах должны отправлять только элементы 2 и 3. Поскольку код обработчика событий для отправки данных уровня данных на каждой странице контролируется разработчиками хоста или маркетинговыми технологами через интерфейс менеджера тегов, бизнес-логика о том, когда и какие элементы уровня данных отправляются на сервер менеджера тегов, может быть изменена и развёрнута за считанные минуты. Взаимодействие с третьими сторонами не требуется: они продолжают получать ожидаемые данные, но теперь из других контекстов, выбранных маркетинговыми технологами хоста.
Смена сторонних поставщиков означает лишь изменение правил распространения данных на сервере менеджера тегов, никаких изменений в коде хоста не требуется. Данные также передаются напрямую только менеджеру тегов, поэтому выполнение происходит быстро. Обработчик событий JavaScript не должен подключаться ко множеству сторонних сайтов.
Косвенные запросы¶
Для косвенных запросов к сайтам менеджеров тегов/агрегаторов, предлагающих GUI для настройки JavaScript, они также могут реализовывать:
- Технические средства контроля, например разрешение JavaScript обращаться только к значениям уровня данных, но не к каким-либо другим элементам DOM
- Ограничение типов тегов, развёртываемых на хост-сайте, например отключение пользовательских HTML-тегов и JavaScript-кода
Компания-хост также должна проверять практики безопасности сайта менеджера тегов, например контроль доступа к конфигурации тегов для компании-хоста. Также может применяться двухфакторная аутентификация.
Предоставление маркетинговым специалистам возможности самостоятельно выбирать источник данных может привести к XSS, поскольку они могут получать данные из параметра URL и помещать их в переменную, находящуюся в выполняемом месте на странице.
Изоляция контента с помощью песочницы¶
Оба инструмента могут использоваться сайтами для помещения в песочницу/очистки DOM-данных.
- DOMPurify — быстрый, толерантный XSS-санитайзер для HTML, MathML и SVG. DOMPurify работает с безопасными настройками по умолчанию, но предлагает широкие возможности настройки и хуков.
- MentalJS — парсер и песочница JavaScript. Реализует allowlist для JavaScript-кода, добавляя суффикс
$к переменным и акцессорам.
Subresource Integrity¶
Subresource Integrity гарантирует выполнение только проверенного кода. Разработчик генерирует метаданные целостности для JavaScript поставщика и добавляет их в элемент script следующим образом:
<script src="https://analytics.vendor.com/v1.1/script.js"
integrity="sha384-MBO5IDfYaE6c6Aao94oZrIOiC7CGiSNE64QUbHNPhzk8Xhm0djE6QqTpL0HzTUxk"
crossorigin="anonymous">
</script>
Важно знать, что для работы SRI хост поставщика должен поддерживать CORS. Также рекомендуется регулярно отслеживать изменения JavaScript поставщика. Потому что иногда можно получить безопасный, но неработающий сторонний код, когда поставщик решает его обновить.
Поддержание JavaScript-библиотек в актуальном состоянии¶
OWASP Top 10 2013 A9 описывает проблему использования компонентов с известными уязвимостями. Это касается и JavaScript-библиотек. JavaScript-библиотеки необходимо поддерживать в актуальном состоянии, поскольку предыдущие версии могут содержать известные уязвимости, делающие сайт уязвимым для атак типа Cross Site Scripting. Существует несколько инструментов для выявления таких библиотек. Одним из них является бесплатный инструмент с открытым исходным кодом RetireJS.
Изоляция с помощью iframe¶
Также можно поместить сторонний JavaScript во iframe с другого домена (например, хоста статических данных). Он будет работать как «тюрьма», и сторонний JavaScript не получит прямого доступа к DOM и cookie главной страницы.
Главная страница хоста и изолированный iframe могут обмениваться данными через механизм postMessage.
Кроме того, iframe можно защитить с помощью атрибута sandbox элемента iframe.
Для высокорисковых приложений рекомендуется использовать Content Security Policy (CSP) в дополнение к изоляции с помощью iframe. CSP делает защиту от XSS ещё более надёжной.
<!-- Some host, e.g. somehost.com, HTML code here -->
<html>
<head></head>
<body>
...
<!-- Include iframe with 3rd party vendor javascript -->
<iframe
src="https://somehost-static.net/analytics.html"
sandbox="allow-same-origin allow-scripts">
</iframe>
</body>
</html>
<!-- somehost-static.net/analytics.html -->
<html>
<head></head>
<body>
...
<script>
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
if (event.origin !== "https://somehost.com:443") {
return;
} else {
// Make some DOM here and initialize other
//data required for 3rd party code
}
}
</script>
<!-- 3rd party vendor javascript -->
<script src="https://analytics.vendor.com/v1.1/script.js"></script>
<!-- /3rd party vendor javascript -->
</body>
</html>
Virtual iframe Containment¶
Эта техника создаёт iFrames, выполняющиеся асинхронно по отношению к главной странице. Она также предоставляет собственный контейнерный JavaScript, который автоматизирует динамическое создание защищённых iFrames на основе требований маркетинговых тегов.
Соглашения с поставщиками¶
Можно включить в соглашение или запрос на предложение с третьими сторонами требование предоставить доказательства применения безопасных практик разработки кода и общей корпоративной безопасности доступа к серверам. Но в частности необходимо определить порядок мониторинга и контроля их исходного кода с целью предотвращения и обнаружения вредоносных изменений этого JavaScript.
MarTechSec¶
Marketing Technology Security (Безопасность маркетинговых технологий)
Относится ко всем аспектам снижения риска от маркетинговых JavaScript-кодов. Средства контроля включают:
- Договорные меры по снижению риска: контракты с любой MarTech-компанией должны включать требование предоставить доказательства безопасности кода и мониторинга его целостности.
- Договорные меры по переносу риска: контракты с любой MarTech-компанией могут включать штрафные санкции за распространение вредоносного JavaScript.
- Технические меры по предотвращению выполнения вредоносного JavaScript: Virtual Iframes.
- Технические меры по выявлению вредоносного JavaScript: Subresource Integrity.
- Технические меры, включающие требования к тестированию на проникновение в части вредоносного поведения клиентского JavaScript.
MarSecOps¶
Marketing Security Operations (Операционная безопасность маркетинга)
Относится к операционным требованиям для поддержания ряда технических мер контроля. Это предполагает возможное взаимодействие и обмен информацией между маркетинговой командой, поставщиком MarTech и командой эксплуатации для обновления информации в элементах управления страницы (изменение SRI-хеша, изменения на страницах с SRI), политик в Virtual iFrames, конфигурации менеджера тегов, изменений уровня данных и т.д.
Наиболее полные и превентивные меры контроля для любого сайта, содержащего нетривиальные маркетинговые теги:
-
Уровень данных, который вызывает маркетинговый сервер или API менеджера тегов, так что на вашей странице выполняется только ваш код (инверсия управления).
-
Virtual frame Containment.
Операционные требования MarSecOps для реализации технических мер контроля в темпе изменений, которого требует маркетинг, или без значительного числа выделенных ресурсов, могут сделать использование уровня данных и Subresource Integrity нецелесообразным.
Ссылки¶
- Widespread XSS Vulnerabilities in Ad Network Code Affecting Top Tier Publishers, Retailers.
- Inside and Beyond Ticketmaster: The Many Breaches of Magecart.
- Magecart – a malicious infrastructure for stealing payment details from online shops.
- Compromised E-commerce Sites Lead to "Magecart"
- Inbenta, blamed for Ticketmaster breach, admits it was hacked.