Комментарии 12
Растет уровень угроз — совершенствуется защита. Совершенствуется защита — совершенствуется малварь. Если исходить из этого, получится замкнутый круг! Сам малварь (его разработка и использование) — всего лишь следствие. Работать необходимо в первую очередь с причиной. Снижение экономической выгоды от использования малваря пропорционально снижению использования малваря. И наоборот.
0
Фильтрация, комплексные средства… Всю статью можно свести к одной фразе:
При выводе значения в HTML-разметку нужно использовать преобразование сущностей.
При выводе значения внутри тега
При этом, если вывод в HTML в атрибут типа
Если у вас такой редкий случай, что пользователь может вводить абсолютный URL полностью, то надо проверять, чтобы он не начинался с
Если у вас такой редкий случай, что вы выводите пользовательское значение внутри тега
Для вывода пользовательского HTML нужно использовать специальные средства типа HTMLPurifier.
Надо понимать, что происходит не просто вывод значения, а вывод значения в определенный контекст.
И пусть пользователь вводит всё что хочет, не надо его ограничивать.
Используйте преобразование сущностей
При выводе значения в HTML-разметку нужно использовать преобразование сущностей.
При выводе значения внутри тега
script
нужно использовать JSON-кодирование. Кавычки для строк вручную писать не надо.При этом, если вывод в HTML в атрибут типа
href
, то перед этим надо дополнительно сделать URL-кодирование для составных частей URL, если в атрибут типа onclick
, то JSON-кодирование.Если у вас такой редкий случай, что пользователь может вводить абсолютный URL полностью, то надо проверять, чтобы он не начинался с
javascript:
, а лучше разрешать только начинающийся с http:/https:
.Если у вас такой редкий случай, что вы выводите пользовательское значение внутри тега
style
, то нужно использовать приведение к int для числовых значений либо добавление слешей к кавычкам для строковых. При этом обрамляющие кавычки лучше добавлять в функции добавления слешей, так же как делает json_encode()
, а не хардкодить в css-разметке. Потому что иначе можно ошибиться и где-нибудь случайно написать кавычки другого типа.Для вывода пользовательского HTML нужно использовать специальные средства типа HTMLPurifier.
Надо понимать, что происходит не просто вывод значения, а вывод значения в определенный контекст.
И пусть пользователь вводит всё что хочет, не надо его ограничивать.
+3
Если у вас такой редкий случай, что пользователь может вводить абсолютный URL полностью, то надо проверять, чтобы он не начинался с javascript:, а лучше разрешать только начинающийся с http:/https:.
так можно пропустить:
http://domain.com" onclick="javascript:...."
0
При выводе значения внутри тега script нужно использовать JSON-кодирование. Кавычки для строк вручную писать не надо.
Можно про этот случай подробнее? Как раз сегодня мучился с задачей как передать объект внутрь script (на стороне фронтенда) при рендеринге темплейта на стороне сервера (express + nunjucks templates). Объект содержит пользовательские данные, то есть может содержать все что угодно. Объект сериализирую в JSON чтобы потом подставить в скрипт и распарсить с помощью JSON.parse. Если выводить напрямую, то включается html экранирование nunjucks и результирующий js получается невалидный. Если отключить экранирование и выводить как есть, то в это чревато вышеописанным XSS. Что-то не получилось нагуглить внятного примера под nodejs, хотя знаю что задача актуальная и существуют методы на других шаблонизаторах (var a = {!JSENCODE(var)} к примеру в Visualforce). Нашел выход один, но так сказать через другое место — выводить JSON как обычный экранированный текст в html тег и потом вытягивать его с помощью innerHTML, а дальше парсить. Но может есть способ элегантнее?
0
Если пользовательские данные это например строка из БД, то можно сделать так:
Пример на PHP, но принцип думаю везде одинаковый. То есть, на клиенте не надо делать JSON.parse, просто сразу объявляем объект, который бразуер распарсит при загрузке страницы.
<script>
var obj = <?= json_encode($data) ?>; // var obj = {field: "user_value", ...};
</script>
Пример на PHP, но принцип думаю везде одинаковый. То есть, на клиенте не надо делать JSON.parse, просто сразу объявляем объект, который бразуер распарсит при загрузке страницы.
0
А что произойдет если в json будет такая штука?
Я без особых знаний данной темы понимаю что ничего хорошего. А если еще применять различные техники скрытия спецсимволов? По вашему примеру получается что $data без экранирования становится частью html разметки.
{field: "</script><script>alert('hacked')", ...};
Я без особых знаний данной темы понимаю что ничего хорошего. А если еще применять различные техники скрытия спецсимволов? По вашему примеру получается что $data без экранирования становится частью html разметки.
0
В PHP json_encode() экранирует слеши. У меня получается такой вывод:
Никаких алертов не происходит.
<?php
$data = ['field' => "</script><script>alert('hacked')"];
?>
<script>
var obj = <?= json_encode($data) ?>;
</script>
<script>
var obj = {"field":"<\/script><script>alert('hacked')"};
</script>
Никаких алертов не происходит.
0
Тогда вопрос сужается.
в NodeJS JSON.stringify не экранирует.
Как это реализовать в NodeJS?
Шаблонизатор (Nunjucks) который я использую не позволяет это сделать из коробки.
Пилить свою функцию которая тупо заменяет какой-то набор спецсимволов не вариант, потому что я не знаю всех возможных вариантов представления исполняемого кода чтобы быть уверенным в том что моя функция 100% рабочаю. Есть ли какое-нибудь готовое решение под NodeJS которое сделает строку безопасной для JS и при этом без всяких html entities которые выплевывает шаблонизатор.
в NodeJS JSON.stringify не экранирует.
Как это реализовать в NodeJS?
Шаблонизатор (Nunjucks) который я использую не позволяет это сделать из коробки.
Пилить свою функцию которая тупо заменяет какой-то набор спецсимволов не вариант, потому что я не знаю всех возможных вариантов представления исполняемого кода чтобы быть уверенным в том что моя функция 100% рабочаю. Есть ли какое-нибудь готовое решение под NodeJS которое сделает строку безопасной для JS и при этом без всяких html entities которые выплевывает шаблонизатор.
0
удалено
0
использование «белых списков» на строне сервера (проверка длины, формата, логики и.д.);Ну, валидацию входных данных нужно делать всегда безотносительно XSS.
В отношении CSP report-uri, кто-нибудь боролся с браузерными плагинами, выполняющимися в контексте текущей страницы и вызывающими ложное срабатывание оповещения? Я так и не смог придумать универсальный способ блокировки хотя бы на стороне сервера.
Сайд-замечание: ваши «клиент-сайд» и «пейлоад» вызывают когнитивный диссонанс между зрением и внутренней речью :)
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Методы обхода защитных средств веб-приложений при эксплуатации XSS-векторов