Перейти к содержанию

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

Идея атаки “межсайтовый скриптинг” (XSS, cross-site scripting) заключается в следующем.
Пользователь отправляет, например, своё имя, заполняя форму. Затем приложение добавляет имя во внутренний список и отображает весь список на странице. Если имена не отображаются безопасно, злоумышленник может отправить JavaScript-код вместо имени, и этот код выполнится в браузере любого другого пользователя, просматривающего список имён.
На рисунке показан базовый пример такой атаки.
Pasted image 20220814145545.png
Здесь шаблон Razor отображает имена с помощью метода @Html.Raw(), который записывает тег <script> прямо в документ. Как только страница загружается в браузере пользователя, тег <script> выполняется, и компьютер пользователя скомпрометирован.

По умолчанию, Razor защищает нас от XSS-атак путём кодирования всех записанных данных в HTML с помощью тег-хелперов, HTML-хелперов или синтаксиса @. Опасность заключается в использовании метода @Html.Raw() — если HTML, визуализируемый этим методом, содержит пользовательский ввод (даже косвенно) — это потенциально уязвимое для XSS-атаки место. Чтобы закодировать содержимое до записи его в вывод, необходимо использовать символ @:
Pasted image 20220814151436.png
В этом примере используется кодирование в HTML для предотвращения непосредственного добавления элементов в HTML DOM. Другой случай — передача недоверенных данных в JavaScript или в значениях URL-запросов.
Например, если в файле Razor есть переменная с именем name, и ее нужно сделать доступной в JavaScript, есть соблазн написать что-то вроде

<script>var name='@name'</script>

Тогда, если имя содержит специальные символы, Razor закодирует их для HTML, что не подходит, когда мы используем строку в контексте JavaScript. Например, двойные кавычки будут закодированы как &quot;, тогда как в данном случае нужно использовать кодировку JavaScript для безопасного символа Unicode: \u0022. Для этого нужно внедрить JavaScriptEncoder в представление, и вызвать метод Encode:
@inject System.Text.Encodings.Web.JavaScriptEncoder encoder;
<script>var name = '@encoder.Encode(name)'</script>

Однако, автор не рекомендует записывать значения в скрипты таким образом. Лучше записать значение в атрибуты HTML-элемента, а затем считать его в переменную JavaScript позже:
<div id="data" data-name="@name"></div>
<script>
    var ele = document.getElementById('data');
    var name = ele.getAttribute('data-name');
</script>


Последнее обновление : 8 мая 2023 г.
Дата создания : 24 октября 2022 г.

Комментарии

Комментарии