XSS: Контексты межсайтового скриптинга

Источник: «Cross-site scripting contexts»
Во время тестирования Отражённого или Сохранённого XSS ключевой задачей является определение контекста XSS: место, где появляются данные и обработка данных приложением.

На основе эти сведений вы можете выбрать одну или несколько полезных нагрузок для XSS-кандидатов и проверить их эффективность.

XSS между HTML тэгами

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

Например:

<script>alert(document.domain)</script>
<img src=1 onerror=alert(1)>

XSS в атрибутах HTML тэга

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

"><script>alert(document.domain)</script>

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

" autofocus onfocus=alert(document.domain) x="

Вышеупомянутая полезная нагрузка создаёт событие onfocus, которое будет выполнять JavaScript, когда элемент получает фокус, а также добавляет атрибут autofocus, для попытки вызова события onfocus автоматически без какого-либо взаимодействия с пользователем. Наконец добавляет x=" изящно исправляя разметку.

Иногда контекст XSS относится к типу атрибута HTML тэга, который сам по себе может создавать контекст доступный для сценариев. В нём вы можете выполнить JavaScript без необходимости завершать значение атрибута. Например, если контекст XSS находится в атрибуте href тега <a>, вы можете использовать псевдо-протокол javascript для выполнения сценария. Например:

<a href="javascript:alert(document.domain)">

Вы можете столкнуться с веб-сайтами кодирующими угловые скобки, но при этом позволяющие вводить атрибуты. Иногда эти инъекции возможны даже внутри тэгов не запускающих событие автоматически. Можно использовать это поведения используя атрибут accesskey для взаимодействия с пользователем в Chrome. accesskey позволяет задать сочетание клавиш ссылающееся на определённый элемент. Атрибут accesskey позволяет определить букву, нажатие на которую в сочетании с другими клавишами (они отличаются в зависимости от платформы) вызовет срабатывание события. Можно использовать эксплойт XSS в скрытых полях input используя метод изобретённый PortSwigger Research.

XSS в JavaScript

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

Завершение существующего скрипта

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

<script>
...
var input = 'controllable data here';
...
</script>

Затем вы можете использовать следующую полезную нагрузку для выхода из существующего JavaScript и выполнения своего:

</script><img src=1 onerror=alert(document.domain)>

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

Выход из JavaScript строки

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

Некоторые полезные способы выхода из строкового литерала:

'-alert(document.domain)-'
';alert(document.domain)//

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

Предположим, что ввод:

';alert(document.domain)//

конвертируется в:

\';alert(document.domain)//

Теперь можно использовать альтернативную полезную нагрузку:

\';alert(document.domain)//

которая преобразуется в:

\\';alert(document.domain)//

Первый обратный слэш означает, что второй интерпретируется буквально, а не как специальный символ. Это означает, что кавычка интерпретируется как признак конца строки и атака завершится успешно.

Некоторые веб-сайты усложняют XSS, ограничивая количество разрешённых символов. Это может быть на уровне веб-сайта или путём разворачивания WAF предотвращающего попадания запросов на веб-сайт. В этих ситуациях нужно поэкспериментировать с другими способами вызова функций обходящими эти меры безопасности. Один из способов сделать это — использовать оператор throw с обработчиком исключения. Это позволяет передавать аргументы функции без использования круглых скобок. Следующий код назначает функцию alert() глобальным обработчиком исключений, а инструкция throw передаёт 1 обработчику исключений (в данном случае alert). Конечным результатом будет вызов функции alert() с 1 в качестве аргумента.

onerror=alert;throw 1

Существует несколько способов использования этой техники для вызова функций без круглых скобок.

Использование HTML-кодирования

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

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

Например, если XSS контекст выглядит следующим образом:

<a href="#" onclick="... var input='controllable data here'; ...">

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

&apos;-alert(document.domain)-&apos;

&apos; — HTML объект представляющий собой апостроф или одинарную кавычку. Поскольку браузер HTML-декодирует значение атрибута onclick перед интерпретацией JavaScript, объекты декодируются как кавычки, ставшие разделителями строк и атака успешно завершится.

XSS в литералах шаблонов JavaScript

Литералы шаблонов JavaScript — строковые литералы, допускающие встраивание JavaScript выражений. Встроенные выражения оцениваются и обычно объединяются с окружающим текстом. Литералы шаблонов заключаются в обратные кавычки вместо обычных кавычек, а встроенные выражения идентифицируются с использованием синтаксиса ${...}.

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

document.getElementById('message').innerText = `Welcome, ${user.displayName}.`;

Когда контекст XSS находится в литерале шаблона JavaScript, нет необходимости завершать литерал. Вместо это нужно использовать синтаксис ${...} для встраивания выражения JavaScript выполняющееся при обработке литерала. Например, если контекст XSS выглядит следующим образом:

<script>
...
var input = `controllable data here`;
...
</script>

вы можете использовать следующую полезную нагрузку для выполнения JavaScript без завершения литерала шаблона:

${alert(document.domain)}

XSS через внедрение шаблона на стороне клиента

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

Дополнительные материалы

Предыдущая Статья

XSS: DOM-based XSS — Основанные на DOM XSS

Следующая Статья

Laravel 10: Стоит ли обновлять?