Более глубокое понимание XSS
В предыдущей части мы говорили о том, что зачастую при атаках нужно адаптировать вредоносный код XSS для обеспечения эффективности в разных ситуациях. Например, если точка внедрения находится в innerHTML, использование <script>alert(1)</script> не даст никакого эффекта. Поэтому нам нужно немного глубже изучить XSS, чтобы знать, какие методы можно использовать для атак.
Изучение атак — это изучение защиты. Чтобы эффективно защищаться, мы должны знать, как атаковать.
Способы выполнения JavaScript
Получив контроль над HTML, вы можете выполнять JavaScript несколькими способами.
Самый распространенный способ - использовать тег <script>. Однако одним из его недостатков является то, что его легко идентифицирует веб-брандмауэр (Web Application Firewall, WAF). Другой недостаток заключается в том, что он не работает в контексте innerHTML, как упоминалось ранее.
Помимо <script>, мы также можем использовать другие теги в сочетании со встроенными обработчиками событий для выполнения кода. Например:
Этот код загружает несуществующее изображение и использует событие `onerror` для выполнения кода.
На самом деле, многие люди (включая меня) используют `x` в качестве `src`, потому что его легко писать и запоминать. Обычно путь `x` не существует, но если он существует, `onerror` не сработает. Поэтому есть шутка, что вы можете разместить изображение с именем `x` в корневом каталоге сайта, и некоторые злоумышленники могут не обнаружить уязвимость XSS.
Помимо `onerror`, можно использовать любой обработчик событий. Например:
Нажатие кнопки вызовет сообщение. Однако отличие этого метода заключается в том, что "пользователь должен выполнить определенное действие", чтобы активировать XSS, например, нажать кнопку. В предыдущем примере с тегом img пользователю ничего не нужно делать, и XSS сработает.
Для более короткого кода можно использовать событие onload в svg:
Немного дополнительной информации: в HTML кавычки (`"`) для значений атрибутов не обязательны. Если в вашем содержимом нет пробелов, вы можете их удалить без проблем. Даже пробелы между тегами и атрибутами можно заменить на `/`. Таким образом, код для svg можно написать так:
Для создания полезной нагрузки XSS не требуются пробелы или кавычки.
Часто используемые обработчики событий включают: 1. onerror 2. onload 3. onfocus 4. onblur 5. onanimationend 6. onclick 7. onmouseenter
Помимо этих обработчиков событий, начинающихся с "on", есть еще один способ выполнения кода, который могли видеть разработчики фронтенда:
Это используется для того, чтобы элемент не реагировал на нажатие. Из этого примера мы видим, что для выполнения кода можно использовать href, например:
Подводя итог, существует несколько способов выполнения JavaScript в HTML:
1. Тег <script> 2. Обработчики событий в атрибутах (начинающиеся с on) 3. Псевдопротокол javascript:
Знание этих методов позволяет использовать их в разных ситуациях.
XSS в различных сценариях и механизмах защиты
Обычно места, куда можно внедрить вредоносный код, называются точками внедрения.
Точка внедрения находится в строке document.querySelector('#name').innerHTML = name.
Различные точки внедрения влияют на то, как можно проводить атаки и как от них защищаться. Давайте рассмотрим три разных сценария.
HTML Injection
Это наиболее распространенный сценарий, будь то приведенный выше пример или фрагмент кода PHP ниже:
В обоих этих случаях вы манипулируете предоставленным вам пустым HTML, поэтому вы можете напрямую писать любые нужные элементы, что дает большую свободу действий.
Например, использование часто встречаемого кода <img src=qweqwe onerror=alert(1)> позволяет выполнить JavaScript.
Метод защиты заключается в замене всех вхождений < и > во входных данных пользователя. Таким образом, они не смогут вставить новые HTML-теги и ничего не смогут сделать.
Attribute Injection
Иногда вы можете столкнуться с кодом, подобно следующему, где в качестве значения атрибута в скобках используется введенное содержимое:
В этом случае использование ранее упомянутого кода <img src=qweqwe onerror=alert(1)> не сработает, потому что введенное значение будет обрабатывается как содержимое атрибута.
Чтобы выполнить XSS в этом сценарии, можно экранировать атрибут и закрыть тег, например: "><img src=qweqwe onerror=alert(1)>. Таким образом, весь HTML превратится в:
После экранирования атрибута можно вставлять нужные HTML-теги.
Из этого случая можно понять, почему я упомянул, что контекст важен. Если вы думаете, что XSS встречается только в первом упомянутом мной сценарии и достаточно обрабатывать символы <>, то в этом контексте это будет неэффективно, потому что злоумышленник может атаковать без использования новых тегов.
Например, используя код " tabindex=1 onfocus="alert(1)" x=", который вообще не содержит <>, HTML превратится в:
В отличие от добавления новых HTML-тегов, этот метод атаки использует событие onfocus исходного тега div для выполнения XSS. Поэтому при фильтрации, помимо <>, необходимо кодировать также символы ' и ".
Кроме того, именно поэтому следует избегать написания кода вроде:
Вышеупомянутый атрибут не заключен в кавычки или апострофы, поэтому даже если мы думаем, что защитили его, закодировав <>"', злоумышленник все равно может добавлять другие атрибуты с помощью пробелов.
JavaScript Injection
Иногда пользовательский ввод отражается не только в HTML, но и в JavaScript-коде. Рассмотрим пример:
Глядя на этот фрагмент кода, можно подумать, что достаточно закодировать кавычки ("), чтобы злоумышленник не смог выйти из строки. Однако такой подход ошибочен. Злоумышленник может закрыть тег скрипта (</script>) и внедрять дальше другие теги.
Поэтому, как и в предыдущих случаях, нужно кодировать не только кавычки, но и символы <, >, '. Это предотвратит выход из строки.
Однако даже при этом стоит учитывать, что добавление пустой строки приведет к ошибке SyntaxError, так как браузер не сможет интерпретировать код как допустимый JavaScript.
Рассмотрим еще один пример:
В этом случае для внедрения кода можно использовать шаблонные строки и синтаксис ${alert(1)}. Хотя для фронтенд-разработчиков такой код выглядит подозрительно, не каждый инженер может его распознать. Возможно, этот код написал бэкенд-разработчик, который просто подумал: "Для многострочных строк нужен этот символ", не осознавая его значения и потенциальных опасностей.
Заключение
В этой части мы углубились в изучение XSS, разобрали различные способы выполнения JavaScript-кода и поняли, что необходимые меры защиты зависят от контекста.
Однако гарантирует ли кодирование символов <>"' полную безопасность? Не всегда.
Существует часто упускаемая из виду ситуация, которую мы кратко упомянули выше, но не обсуждали подробно. Мы познакомимся с этим далее.
Прежде чем перейти к следующей части, давайте проведем мозговой штурм. Ранее я упоминал, что в основном существует три способа выполнить JavaScript-код:
1. Тег <script> 2. Обработчики событий в атрибутах (всегда начинающиеся с "on") 3. Псевдопротокол javascript:
Если первый метод, например innerHTML = '<script>alert(1)</script>', не работает, если невозможно использовать обработчики событий и псевдопротокол javascript:, а точка внедрения - innerHTML = data, какие еще способы можно использовать для выполнения скриптов? Подумайте над этим.
Last updated