noscript xss warning что это

xss уязвимость

Угрозы xss атак с применением javascript

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

Что такое xss атака?

Это такой тип атак, который внедряет в веб-системы вредоносный код, заставляя её выдавать измененные данные, подменяет ссылки (видимые/скрытые) или выводит собственную рекламу на пораженном ресурсе.

Существует два направления атак:

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

Активные – это вид атак, когда хакер пытается найти уязвимость в фильтре сайта. Как же реализуется такая атака? Все очень просто. Нужно при помощи комбинации тегов и символов создать такой запрос, чтобы сайт его понял и выполнил команду. Как только дыра в безопасности найдена, в наш запрос можно вложить «вредокод», который, к примеру, будет воровать cookie и пересылать в удобное нам место. Приведем пример скрипта, ворующего “печеньки” с сайта:

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

Правила безопасности

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

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

1. Одно из самых первых и основных правил для разработчика – это применение любого (хотя-бы самого минимального) фильтра.

В проведенном нами исследовании сайтов почти все они были защищены, но все же находились и те, которые не использовали никакой фильтрации получаемых данных. В основном, это встречается на сайтах, написанных на языке PHP. Но, например, в фраемворках python, таких как: flask или Django уже есть встроенные минимальные фильтры, их остается только усилить.

2. Фильтрация символов и вложенных конструкций.

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

3. Фильтр должен учитывать всевозможные комбинации символов.

Одной из наших любимых проверок на xss уязвимость является использование открытых и закрытых скобок.
Например: “/?,#”>>>><

Источник

Отраженный XSS

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

noscript xss warning что это. Смотреть фото noscript xss warning что это. Смотреть картинку noscript xss warning что это. Картинка про noscript xss warning что это. Фото noscript xss warning что это

На странице вы увидите простое поле поиска и кнопку. Для выполнения атаки вам нужно напечатать вот что:

в этом текстовом поле, а затем нажать на кнопку. Вы увидите, как ваше сообщение, «XSS here!», всплывет в новом окне.

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

Вы, возможно, думаете «Ну да, это забавно, но как злоумышленник воспользуется этим, чтобы меня взломать? Я печатаю в моем собственном окне поиска». Один из способов – это фишинговые ссылки. Допустим, вы хозяин сайта. Злоумышленник может создать ссылку, ведущую на ваш сайт, и прицепит к ее концу скрипт, к примеру, вот так:

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

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

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

Давайте посмотрим, как работает эта атака, выполнив второе упражнение XSS Game. Чтобы перейти к нему, нужно выполнить первое, поэтому следуйте инструкциям из первой части статьи.

noscript xss warning что это. Смотреть фото noscript xss warning что это. Смотреть картинку noscript xss warning что это. Картинка про noscript xss warning что это. Фото noscript xss warning что это

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

Как только вы опубликуете это, вы увидите попап-окошко с сообщением «XSS alert!». И не только! Если вы уйдете с этой страницы и вернетесь назад, вы снова увидите окошко. Атака хранится в вашем комментарии на странице чата, и покажет всплывающее окно всем, кто перейдет туда.

Давайте разберем наш скрипт, чтобы понять, что же он делает:

Красный текст означает, что мы передаем изображение.

Синий текст сообщает серверу источник изображения. Тут-то и таится фокус – такого URL, как «foobar», не существует, и картинка не может загрузиться.

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

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

Источник

Общая информация

Что такое XSS?

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

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

Как проводится инъекция вредоносного JavaScript

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

В примере ниже приведен простой серверный скрипт, отображающий последний комментарий на сайте:

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

XSS-атаки

Агенты XSS-атаки

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

Пример сценария атаки

В этом примере мы предположим, что цель злоумышленника – украсть временные файлы (cookies) пользователя, используя XSS-уязвимость сайта. Это можно сделать, заставив браузер жертвы обработать код:

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

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

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

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

noscript xss warning что это. Смотреть фото noscript xss warning что это. Смотреть картинку noscript xss warning что это. Картинка про noscript xss warning что это. Фото noscript xss warning что это

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

Источник

Лучшие практики и рекомендации по защите php-приложений от XSS-атак

Лучшие практики и рекомендации по защите php-приложений от XSS-атак

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

noscript xss warning что это. Смотреть фото noscript xss warning что это. Смотреть картинку noscript xss warning что это. Картинка про noscript xss warning что это. Фото noscript xss warning что это

Большинство уязвимостей связано с неправильной обработкой данных, получаемых извне, или недостаточно строгой их проверкой. Одной из таких уязвимостей является межсайтовое выполнение сценариев (Сross Site Sсriрting, XSS), которая может привести к дефейсу сайта, перенаправлению пользователя на зараженный ресурс, вставке в веб-ресурс вредоносного кода, краже COOKIE-файлов, сессии и прочей информации. Противостоять XSS своими сила поможет применение лучших практик и рекомендаций по безопасному программированию, о которых и пойдет речь ниже.

Лучшие практики и рекомендации:

1. Используйте экранирование входных\выходных данных. Применяйте встроенные функции для очистки кода от вредоносных скриптов. К ним относятся такие функции как htmlspecialchar(), htmlentities() и strip_tags().
Примеры использования:

Встроенные функции PHP, в отличие от самописных, работают гораздо быстрее, а также имеют меньше ошибок безопасности и уязвимостей, т.к. постоянно совершенствуются. Также рекомендуется использовать специальные библиотеки, построенные на основе встроенных функций и фильтров. В качестве примера можно привести OWASP Enterprise Security API (ESAPI), HTML Purifier, Reform, ModSecurity.
Для того чтобы библиотека работала правильно, её нужно предварительно настроить!

2. Используйте подход «белые списки». Подход работает по принципу «что не разрешено, то запрещено». Это стандартный механизм валидации полей для проверки всех входных данных, включая заголовки, куки, строки запросов, скрытые поля, а также длина полей форм, их тип, синтаксис, допустимые символы и другие правила, прежде чем принять данные, которые будут сохраненные и отображены на сайте. Например, если в поле нужно указать фамилию, необходимо разрешить только буквы, дефис и пробелы. Если отклонить все остальное, то фамилия д’Арк будет отклонена — лучше отклонить достоверную информацию, чем принять вредоносные данные.
К сожалению, со своей задачей встроенные фильтры валидации данных PHP не справляются, поэтому рекомендуется писать собственные фильтры и «допиливать» их по мере необходимости. Таким образом, со временем ваши входные методы фильтрации будут усовершенствованы. Стоит также не забывать, что существует слишком много типов активного содержимого и способов кодирования для обхода подобных фильтров. По этой же причине не используйте проверку по «черному списку».

3. Указывайте кодировку на каждой веб-странице. Для каждой веб-страницы необходимо указывать кодировку (например, ISO-8859-1 или UTF-8) до каких-либо пользовательских полей.
Пример использования:

Если в http-заголовке или в метатегах кодировка не указана, браузер пытается сам определить кодировку страницы. Стандарт HTML 5 не рекомендует использовать такие кодировки, которые включают JIS_C6226-1983, JIS_X0212-1990, HZ-GB-2312, JOHAB (Windows code page 1361), а также кодировки, основанные на ISO-2022 и EBCDIC. Кроме того, веб-разработчики не должны использовать CESU-8, UTF-7, BOCU-1 и кодировки SCSU. Эти кодировки никогда не предназначались для веб-контента[1]. В случае если тег расположен до тега и заполняется пользовательскими данными, злоумышленник может вставить вредоносный html-код в кодировке UTF-7, обойдя, таким образом, фильтрацию таких символов, как ‘ session.cookie_httponly = True

— в скрипте через функцию session_set_cookie_params() [3]:

— в веб-приложении через функцию setcookie() [4]:

Эта функция поддерживается последними версиями распространенных браузеров. Однако старые версии некоторых браузеров через XMLHttpRequest и другие мощные браузерные технологии обеспечивают доступ для чтения HTTP-заголовков, в том числе и заголовка Set-Cookie, в котором установлен флаг HttpOnly[5].

5. Использовать Content Security Policy (CSP). Это заголовок, который позволяет в явном виде объявить «белый список» источников, с которых можно подгружать различные данные, например, JS, CSS, изображения и пр. Даже если злоумышленнику удастся внедрить скрипт в веб-страницу, он не выполниться, если не будет соответствовать разрешенному списку источников.
Для того чтобы воспользоваться CSP, веб-приложение должно через HTTP-заголовок «Content-Security-Policy» посылать политику браузеру.
Пример использования:

‘Content-Security-Policy’ — это официальный http-заголовок, утвержденный W3C, который поддерживается браузерами Chrome 26+, Firefox 24+ и Safari 7+. HTTP-заголовок «X-Content-Security-Policy» используется для Firefox 4-23 и для IE 10-11, заголовок «X-Webkit-CSP» – для Chrome 14-25, Safari 5.1-7[6].

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

6. Регулярно проводите анализ безопасности кода и тестирование на проникновение. Используйте как ручной, так и автоматизированный подходы. Такие инструменты как Nessus, Nikto и OWASP Zed Attack Proxy помогут обнаружить уязвимости XSS в вашем веб-приложении.

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

Автор статьи: Внештатный сотрудник PentestIT, Сергей Сторчак

Источник

Книга «Безопасность в PHP» (часть 3). Межсайтовый скриптинг (XSS)

noscript xss warning что это. Смотреть фото noscript xss warning что это. Смотреть картинку noscript xss warning что это. Картинка про noscript xss warning что это. Фото noscript xss warning что это

Межсайтовый скриптинг (XSS) — пожалуй, самый типичный вид уязвимостей, широко распространённых в веб-приложениях. По статистике, около 65 % сайтов в той или иной форме уязвимы для XSS-атак. Эти данные должны пугать вас так же, как пугают меня.

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

XSS-атака происходит, когда злоумышленник получает возможность внедрить скрипт (зачастую JavaScript) в страницу, выдаваемую веб-приложением, и выполнить его в браузере клиента. Обычно это делается с помощью переключения контекста данных HTML в скриптовый контекст, чаще всего — когда внедряется новый код HTML, Javascript или CSS-разметка. В HTML достаточно мест, где можно добавить в страницу исполняемый скрипт, а браузеры предоставляют немало способов сделать это. Любые входные данные веб-приложения, например параметры HTTP-запросов, способны внедрить код.

Одна из проблем, связанных с XSS, — постоянная недооценка со стороны программистов, нетипичная для уязвимостей такого серьёзного уровня. Разработчики зачастую не представляют себе степень угрозы и обычно строят защиту, основанную на неверных взглядах и плохих подходах. Особенно это касается PHP, если код пишут разработчики без достаточных умений и познаний. Кроме того, реальные примеры XSS-атак выглядят простыми и наивными, так что изучающие их программисты считают свою защиту достаточной, пока она их устраивает. Нетрудно понять, откуда взялись 65 % уязвимых сайтов.

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

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

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

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

Внедрённые скрипты могут быть использованы для самых разных задач. Это:

и т. д., продолжать можно до бесконечности.

Подмена интерфейса (UI Redress, clickjacking)

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

Подменой интерфейса называется любая попытка атакующего изменить пользовательский UI веб-приложения. Это позволяет атакующему внедрять новые ссылки, новый HTML-код, чтобы изменить размеры, скрыть/перекрыть оригинальный интерфейс и т. д. Если такая атака выполняется для обмана пользователя, чтобы он нажал на внедрённую ссылку или кнопку, тогда обычно её относят к кликджекингу.

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

Пример межсайтового скриптинга

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

Каким-то чудом движок форума включает эту подпись во все заспамленные топики, и пользователи начинают загружать этот код. Результат очевиден. Злоумышленник внедряет в страницу элемент iframe, который будет отображаться как крошечная точка (нулевого размера) в самом низу страницы, не привлекая никакого внимания. Браузер отправит запрос на содержимое iframe, и в URI злоумышленника будут переданы значения кук каждого участника форума в виде GET-параметра. Их можно сопоставить и использовать для дальнейших атак. В то время как обычные участники злоумышленнику неинтересны, хорошо спланированный троллинг, несомненно, привлечёт внимание модератора или администратора, чьи куки могут оказаться очень полезными для получения административного доступа к форуму.

Это простой пример, но вы можете расширить его. Допустим, злоумышленник захочет узнать имя пользователя, ассоциированного с украденными куками. Легко! Достаточно добавить к URL злоумышленника код DOM-запроса, который вернёт имя и включит его в параметр username= GET-запроса. Или злоумышленнику понадобилась информация о браузере для обхода fingerprint-защиты сессии? Достаточно включить данные с navigator.userAgent.

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

Конечно, в этом примере в подходе злоумышленника есть изъян. Рассмотрим очевидный способ защиты. Все куки с конфиденциальными данными помечены флагом HttpOnly, который запрещает JavaScript доступ к данным этих файлов. В принципе, вы должны помнить, что если злоумышленник внедрит JavaScript, то этот скрипт сможет делать что угодно. Если у злоумышленника не вышло получить доступ к куке и провести атаку с её использованием, то он сделает то, что должны делать все хорошие программисты: напишет код для эффективной автоматизированной атаки.

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

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

Типы XSS-атак

Атаки с помощью XSS можно классифицировать несколькими путями. Один из них — по способу попадания вредоносных входных данных в веб-приложения. Во входные данные приложения может быть включён результат текущего запроса, сохранённый для включения в последующий выходной запрос. Или данные могут быть переданы в DOM-операции на базе JavaScript. Таким образом, получаются следующие типы атак.

Отражённая XSS-атака

Здесь ненадёжные входные данные, отправленные веб-приложению, включаются сразу в выходные данные приложения, т. е. «отражаются» от сервера к браузеру в одном и том же запросе. Отражение бывает с сообщениями об ошибках, поисковыми материалами, предварительными просмотрами постов и т. д. Эта форма атаки может быть организована, чтобы убедить пользователя перейти по ссылке или отправить данные из формы злоумышленника. Чтобы заставить пользователя нажать на ненадёжные ссылки, иногда требуется социальная инженерия, атака подмены интерфейса или сервис сокращения ссылок. Социальные сети и сами сервисы сокращения ссылок особенно уязвимы для подмены URL-адресов с использованием сокращённых ссылок, поскольку такие ссылки — обычное явление на данных ресурсах. Будьте осторожны и внимательно проверяйте, на что нажимаете!

Хранимая XSS-атака

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

XSS-атака на основе DOM

Атака на основе DOM может быть как отражённой, так и хранимой. Различие в том, на что направлена атака. Чаще всего пытаются сразу же изменять разметку HTML-документа. Однако HTML можно изменять и с помощью JavaScript, используя DOM. Успешно внедрённые в HTML элементы в дальнейшем могут быть использованы в DOM-операциях в JavaScript. Целями атак становятся также уязвимости в JS-библиотеках или их неправильное применение.

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

XSS-атака успешна, если в ходе неё внедряется контекст. Термин «контекст» описывает то, как браузеры интерпретируют содержимое HTML-документа. Браузеры распознают ряд ключевых контекстов, включая HTML-код, атрибуты HTML, JavaScript, URL, CSS.

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

$colour заполняется из базы данных настроек пользователя, которые влияют на цвет фона для текстового блока. Значение вводится в контексте CSS, дочернем по отношению к контексту HTML-атрибута. То есть мы добавили CSS в атрибут style. Может показаться, что необязательно избегать такой ловушки с контекстом, но посмотрим на следующий пример:

Если атакующий успешно внедрит этот colour, то он может внедрить CSS-выражение, которое выполнит определённый JavaScript в браузере Internet Explorer. Другими словами, злоумышленник сумеет переключить текущий контекст путём введения нового контекста JavaScript.

Посмотрев на предыдущий пример, некоторые читатели вспомнят об экранировании (escaping). Воспользуемся им:

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

Что пошло не так в предыдущем примере? Что заставило браузер деэкранировать атрибуты HTML перед интерпретацией контекста? Мы проигнорировали тот факт, что необходимо экранировать два контекста.

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

Давайте рассмотрим ещё один пример:

Если не принимать во внимание ненадёжные входные данные, то этот код можно проанализировать следующим образом:

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

Защита от межсайтового скриптинга

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

Проверка входных данных

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

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

Проверка входных данных помогает контролировать данные с определённым синтаксисом. Например, допустимый URL-адрес должен начинаться с префикса http:// или https://, а не с гораздо более опасных конструкций javascript: или data:. По сути, все адреса, полученные из непроверенных входных данных, должны проверяться на наличие этих тегов. Экранирование URI javascript: или data: имеет такой же эффект, как экранирование легального URL-адреса. То есть вообще никакого эффекта.

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

Экранирование (а также кодирование)

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

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

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

Никогда не вводите данные, за исключением ввода из доверенных мест

Прежде чем изучать стратегии экранирования, необходимо убедиться, что шаблоны вашего веб-приложения не теряют (misplace) данные. Это относится к внедрению данных в чувствительные области HTML, которые дают злоумышленнику возможность влиять на порядок обработки разметки и которые обычно не требуют экранирования при использовании программистом. Рассмотрим примеры, где [… ] — это внедряемые данные:

Каждое из вышеперечисленных мест опасно. Разрешение данных в теге script, вне строковых и числовых литералов, позволяет при атаке внедрить JavaScript. Данные, помещённые в HTML-комментарии, могут быть использованы для запуска условных выражений (conditionals) Internet Explorer и для других непредвиденных действий. Следующие два места более очевидны, так как никто не позволил бы злоумышленнику влиять на свои теги или названия атрибутов — мы как раз пытаемся это предотвратить! Наконец, как и в случае со скриптами, мы не можем позволить злоумышленникам внедряться непосредственно в CSS, так как это даст возможность проводить атаки подмены интерфейса и выполнять скрипты, используя поддерживаемую в Internet Explorer функцию expression().

Всегда экранируйте HTML до внедрения данных в HTML-тело

Экранирование HTML хорошо известно в PHP в виде функции htmlspecialchars().

Всегда экранируйте HTML-атрибуты до внедрения данных в их контекст

Контекст HTML-атрибута ссылается на все значения элемента, за исключением свойств, которые интерпретируются браузером как CDATA. Это исключение довольно запутанное, но в основном оно относится к HTML-стандартам, основанным не на XML, где JavaScript может включаться в атрибуты события в неэкранированном виде. Для всех других атрибутов у вас есть следующие два варианта:

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

Всегда экранируйте JavaScript до внедрения в значения данных

Значения данных в JavaScript в основном строковые. Поскольку вы не можете экранировать числа, есть дополнительное правило: всегда проверяйте валидность чисел.

Политика защиты контента

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

Политика защиты контента (CSP) — это HTTP-заголовок, передающий белый список надёжных источников ресурсов, которым браузер может доверять. Любой источник, не указанный в списке разрешённых, причисляется к ненадёжным и просто игнорируется. Рассмотрим следующее:

Этот заголовок CSP сообщает браузеру, что нужно доверять только тем адресам источника JavaScript, которые указывают на текущий домен. После браузер будет загружать скрипты из этого источника, но полностью игнорировать все остальные. Это означает, что http://attacker.com/naughty.js не загрузится, если злоумышленник каким-то образом сумеет его внедрить. Кроме того, все встроенные скрипты, например теги

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

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

Формат значения заголовка очень прост. Значение состоит из директивы script-src, после которой идёт список разделённых пробелами источников, применяемый в качестве белого списка. Источником может быть ключевое слово в кавычках, такое как ‘self’, или URL. Значение URL-адреса сопоставляется с полученным списком. Информация, отсутствующая в URL, может быть свободно изменена в документе HTML. Указание http://code.jquery.com предотвращает загрузку скриптов с http://jquery.com или http://domainx.jquery.com, потому что мы явным образом задали разрешённые домены. Чтобы разрешить все поддомены, можно указать просто http://jquery.com. То же самое относится и к локальным путям, портам, URL-схемам и т. д.

Суть белого списка CSP проста. Если вы создадите список ресурсов конкретного вида, то всё, что в него не войдёт, не загрузится. Если вы не определите список для типа ресурсов, то браузер по умолчанию отбрасывает все ресурсы этого типа.

Поддерживаются следующие директивы ресурсов:

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

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

Кроме URL, разрешённым источникам можно назначить следующие ключевые слова, которые должны быть записаны в одинарных кавычках:

Вы заметили слово unsafe, т. е. «небезопасно»? Лучший способ применения CSP — не выбирать подходы, которые выбирают злоумышленники. Они хотят внедрять inline-скрипты или другие ресурсы? Если мы сами избежим inline-применения, то наши веб-приложения могут приказать браузерам игнорировать всё inline-содержимое без исключения. Будем использовать внешние файлы скриптов и функции addEventListener() вместо атрибутов событий. Но раз вы придумываете для себя правило, то не обойтись и без нескольких полезных исключений, не так ли? Не так. Забудьте о любых исключениях. Включение параметра ‘unsafe-inline’ противоречит самой цели применения CSP.

Ключевое слово ‘none’ означает именно «ничего». Если установить его в качестве источника ресурса, то параметр заставит браузер игнорировать все ресурсы указанного типа. Это добавит вам мелких проблем, но я советую сделать что-то наподобие следующего примера, чтобы белый список вашего CSP всегда ограничивался только тем, что он разрешает явно:

И последнее предостережение. Поскольку CSP — новое решение, вам потребуется дублировать заголовок X-Content-Security-Policy, чтобы убедиться, что его поймут и WebKit-браузеры, такие как Safari и Chrome. Подарок от WebKit для вас.

Определение браузера пользователя

Очистка HTML

В какой-то момент веб-приложение столкнётся с необходимостью включать задаваемый извне HTML-код в свою веб-страницу без применения к нему экранирования. Наглядные примеры: цитирование сообщений на форуме, комментарии в блоге, формы редактирования и записи из RSS или Atom. Если такие данные подвергнуть экранированию символов, то они будут искажены и испорчены, поэтому вместо экранирования здесь приходится тщательно фильтровать данные, чтобы убедиться, что все опасные элементы устранены.

Вы заметили, что я написал об HTML-коде «задаваемый извне», а не «создаваемый извне»? Множество веб-приложений позволяют пользователям вместо HTML-разметки включать такие альтернативы, как BBCode, Markdown или Textile. Распространённая ошибка в PHP — мнение, что эти языки разметки предотвращают XSS-атаки. Полный бред. Цель этих языков — позволить пользователям проще и легче создавать форматированный текст, обходясь без работы с HTML. Не все знают HTML, да и сам этот язык не в точности соответствует своим SGML-корням. Вручную создавать длинные блоки форматированного текста в HTML — долго и мучительно.

HTML из таких входных данных генерируется на сервере. Это подразумевает под собой доверительные операции, само доверие к которым — распространённая ошибка. Получаемый в результате таких операций HTML по-прежнему «заданный извне». Мы не можем считать его безопасным. Это более очевидно на примере ленты блога, чьи записи ещё до момента генерирования являются валидным HTML.

Рассмотрим следующий фрагмент кода:

BB-код ограничивает HTML по умолчанию, но это не даёт абсолютной неуязвимости. Например, большинство генераторов не заметят использования HTTP URL’ов и пропустят их. Выделение Markdown:

Markdown — популярная альтернатива для написания HTML, но он также позволяет авторам смешивать HTML с Markdown. Это действительно так, генераторы Markdown не обращают внимания на включённую XSS-нагрузку.

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

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

Единственная библиотека в PHP, которая действительно выдаёт безопасный HTML, — HTMLPurifier. Она активно поддерживается, в значительной степени проверена, и я настоятельно рекомендую её. С HTMLPurifier достаточно просто работать, по сути, требуется только задать разрешённые элементы:

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *