XSS атакует! Краткий обзор XSS уязвимостей

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

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

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

Что такое XSS

Пересказывая своими словами определение с википедии, XSS (Cross-site scripting) - это тип уязвимости, встречающийся в web приложениях. XSS атаки позволяют внедрить вредоносный скрипт (или как его еще часто называют эксплойт) на страницу приложения, в результате чего у пользователей, посещающих эту страницу, могут украсть данные разной степени чувствительности (куки, сессионные токены, логины с паролями и просто личную информацию о пользователе).

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

Также, наверно, более популярный способ, когда злоумышленник передает вредоносный пэйлоад прямо в ссылке на наше приложение в параметрах запроса или в хэше, который читается в JS и может быть выполнен. Чаще всего это «отраженные» либо «основанные на DOM» XSS атаки, о них тоже чуть позже.

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

  • SOP (Same-Origin Policy) (https://developer.mozilla.org/ru/docs/Web/Security/Same-origin_policy) - политика позволяющая определить, какие стрипты будут иметь доступ к данным, а какие нет, точнее даже с каких ресурсов мы разрешаем скриптам получать данные пользователя. Простыми словами помогает запретить скриптам с одного домена получить доступ к данным пользователя от другого домена.

  • CSP (Content Security Policy) (https://developer.mozilla.org/ru/docs/Web/HTTP/CSP) - политика, которая позволяет установить список доверенных источников скриптов, все скрипты из других источников просто будут проигнорированы.

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

Но не смотря на все это XSS все еще возможен, да и в целом полезно знать о таких вещах, в конце концов даже на собеседовании могут спросить:)

Типы XSS атак

Я хочу рассмотреть 3 основных типа XSS (на самом деле их больше, но эти 3 типа наиболее распространены):

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

  • Отраженный - при такой уязвимости база не участвует в доставке вредоносного скрипта жертве, то есть эксплойт нигде не хранится, атака обычно происходит через URL, когда например вредоносный скрипт пробрасывается через query параметры запроса, «отражается от сервера», где в процессе формирования страницы скрипт добавляется в тело ответа и пользователь получает страницу с уже встроенным в нее скриптом.

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

Давайте теперь поподробнее разберем каждый из типов.

Сохраняемый XSS

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

function addReviews() {
  // В примере я намеренно использую var, тк сложно себе представить в современном приложении, использующем ES6 синтаксис такую реализацию :)
  var reviews = getReviews();
  reviews.forEach(function (review) {
    var reviewsList = document.getElementById("reviews");
    reviewsList.innerHTML += "<li>" + review + "</li>";
  })
}
addReviews()
<ul id=«reviews»></ul>

В таком случае злоумышленник может добавить свой отзыв:

Товар говно
<script>
    alert(document.cookie);
</script>

Далее у каждого, кто посмотрит этот комментарий отобразится только «Товар говно», но помимо этого выскочит alert со всеми  его куками (вместо этого злоумышленник скорее всего сделает запрос, в теле которого передаст все добытые данные о пользователе к своему серверу).

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

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

Microsoft Teams — Cross Site Scripting (XSS) Bypass CSP | by Numan Turle | Medium

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

Отраженный XSS

В отраженном XSS реализация доставки вредоносного скрипта выглядит иначе. Скрипт не должен сохраняться на серверах приложения, он попадает жертве через ссылку.  Из этого следует очевидный вывод, что каждому отдельному пользователю, на которого осуществляется атака, нужно дать такую ссылку лично, например по почте или во время личной переписки, хотя ссылка может быть размещена на сайте злоумышленника, на который тем или иным способом попала жертва и тыкнула на нее, но опять же, скорее всего на этот сайт вы попали по ссылке из email’а или из личной переписки. Дальше по этой ссылке (в которой в query параметрах зашит скрипт) мы попадаем на страничку, которую сформировал сервер, отталкиваясь от содержания ссылки, и добавляя в страничку все те параметры, что в ней имеются. Не трудно догадаться, что скрипт, который добавил злоумышленник в параметры, тоже попадет в сформированный HTML  и благополучно запустится у жертвы. Тут уже злоумышленник может отправить себе ваши куки или собрать другие чувствительные данные со страницы и тоже отправить их  себе.

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

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

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

XSS на основе DOM

Такой тип XSS атак нацелен непосредственно на внедрение скрипта в DOM дерево нашего приложения именно во время отработки JS. Например как и в случае с отраженным XSS, мы можем пробросить вредоносный скрипт через query параметр, но в отличии от предыдущего примера, наше приложение не добавит этот скрипт в HTML и вернет пользователю страничку без эксплойта. Далее, после того как клиент загрузил страницу и все необходимые для ее работы файлы, у клиента запускается JS, который для тех или иных целей обращается к document.location, чтобы достать оттуда данные из query параметра (в котором лежит наш вредоностный скрипт) и например добавить эти данные на страницу пользователя, после этого скрипт запускается, имея в свою очередь доступ к личным данным пользователя.

Учитывая то, что в современной веб индустрии большинство приложений - это SPA, реализованные на react, angular, vue и других фреймворках, где большАя часть логики перенесена на сторону клиента и страницы формируются именно на основе работы JS в браузере, XSS уязвимости на основе DOM встречаются чаще всего.

давайте разберем пример:

Представьте, что мы работаем над банковским веб приложением, в котором есть раздел ответов на вопросы, каждый из ответов в нем выглядит как отдельная статья. Банк довольно большой, соответственно вопросов к нему тоже много :) В какой-то момент принимается решение, что для удобства нужно сделать поиск по разделу:

<form>
    <label for="search">Поиск:</label>
    <input type="text" id="search-box" name="search-box">
    <button type="submit" id="search-button">Найти</button>
</form>

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

function updateSearchQueryParam(value) {
    const queryParams = new URLSearchParams(window.location.search);
    queryParams.set('search', value);

    const newPath = window.location.pathname + '?' + queryParams.toString();

    history.pushState(null, '', newPath);
}


function updateSearchSubtitle() {
    const searchFromQuery = new URLSearchParams(window.location.search).get('search');
    const searchSubtitle = document.getElementById('searchSubtitle');

    if(searchFromQuery) {
        searchSubtitle.innerHTML = 'Результаты поиска по запросу' + searchFromQuery;
    }
}

Функцию updateSearchQueryParam мы вызываем каждый раз, когда совершаем поиск, чтобы записать в query параметр то, что ищим, а функцию updateSearchSubtitle также вызываем при каждом поиске, а также при загрузке страницы, чтобы если в query параметре что-то было, мы это отобразили.

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

Кстати говоря такую уязвимость все еще можно отследить на стороне сервера, если мы пишем логи всех запросов, в них будет видно, что приходил подозрительный запрос со скриптом в значении одного из query параметров, но как я говорил ранее, бывают случаи, когда скрипт не покидает границ браузера. Например, если в нашем приложении мы работаем не с query параметром, а с hash. Как известно, то что мы пишем в hash ссылки не улетает на сервер, но JS без проблем может работать с тем, что мы туда передали.

Другие типы XSS атак

Скажу еще пару слов о других типах XSS атак, они не так распространены, но думаю знать об их существовании будет не лишним.

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

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

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

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

Источник: https://habr.com/ru/post/717896/


Интересные статьи

Интересные статьи

Я думаю, многим знакома ситуация, когда в сжатые сроки необходимо ознакомиться с большим объёмом текстов – статей, обзоров, сюжетов, отзывов и так далее.
Всем доброго времени суток!Публикую обзор книги "Python для чайников" от автора Джон Пола Мюллера.Ссылку на бесплатную электронную версию этой книги оставлю в конце поста.Стоит читать? Нет! Почему? Оп...
Web Summit — самая крупная технологическая конференция в мире, которая ежегодно проводится в Лиссабоне, — в этом году прошла с 1 по 4 ноября и собрала 42 000 участников.Представители российской к...
Правила YARA используются для классификации и идентификации образцов вредоносных программ путем создания описаний их семейств на основе текстовых или двоичных шаблонов.
Современная корпоративная ИТ-инфраструктура состоит из множества систем и компонентов. И следить за их работой по отдельности может быть довольно сложно — чем больше предприятие, тем ...