Руководство по снижению угроз для интерактивного рендеринга на стороне сервера в ASP.NET Core Blazor.
Примечание.
Это не последняя версия этой статьи. В текущем выпуске см. версию .NET 9 этой статьи.
Внимание
Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
В текущем выпуске см . версию .NET 9 этой статьи.
В этой статье объясняется, как устранять угрозы безопасности на интерактивной стороне Blazorсервера.
Приложения принимают модель обработки данных с отслеживанием состояния, где сервер и клиент поддерживают длительные отношения. Устойчивое состояние обеспечивается цепью, которая может охватывать соединения, которые могут потенциально существовать длительное время.
Когда пользователь посещает сайт , сервер создает канал в памяти сервера. Канал указывает браузеру, какое содержимое подготавливается к просмотру, и реагирует на события, например, когда пользователь нажимает кнопку в пользовательском интерфейсе. Для выполнения этих действий канал вызывает функции JavaScript в браузере пользователя и методах .NET на сервере. Это двустороннее взаимодействие на основе JavaScript называется взаимодействием с JavaScript (взаимодействием JS).
Поскольку JS взаимодействие происходит через Интернет и клиент использует удаленный браузер, приложения сталкиваются с большинством проблем безопасности, характерных для веб-приложений. В этом разделе описаны распространенные угрозы для серверных Blazor приложений и рекомендации по устранению угроз, ориентированные на приложения, подключенные к Интернету.
В ограниченных средах, например в корпоративных сетях или интрасетях, некоторые рекомендации по устранению рисков либо:
- Не применяется в ограниченной среде.
- либо не стоят своих затрат на реализацию, поскольку в ограниченной среде угроза безопасности минимальна.
Интерактивные компоненты сервера с включенным сжатием WebSocket
Сжатие может подвергнуть приложение побочным канальным атакам против шифрования TLS соединения, таким как CRIME и BREACH атаки. Эти типы атак требуют, чтобы кибератакующий:
- Принудить браузер отправлять запросы с данными, которыми управляет кибератакующий, на уязвимый сайт с помощью межсайтовой отправки форм или внедрения сайта в iframe другого сайта.
- Просмотрите длину сжатого и зашифрованного ответа по сети.
Чтобы приложение было уязвимым, оно должно отображать нагрузку кибератакующего в ответе, например путем записи пути или строки запроса в ответ. Используя длину ответа, кибератака может "угадать" любую информацию о ответе, обходя шифрование подключения.
Как правило, Blazor приложения могут включать сжатие по подключению WebSocket с соответствующими мерами безопасности:
Приложение может быть уязвимо, если оно принимает содержимое из запроса (например, путь или строка запроса), которое может влиять на кибератаку и воспроизводит его в HTML-код страницы или в противном случае делает его частью ответа.
Blazor Применяет следующие меры безопасности автоматически:
При настройке сжатия Blazor автоматически блокирует внедрение приложения в iframe, что препятствует отображению начального (несжатого) ответа сервера и не позволяет подключению WebSocket даже начаться.
Ограничение на встраивание приложения в iframe может быть ослаблено. Тем не менее, расслабление ограничения подвергает приложение атаке, если внедренный документ будет скомпрометирован через уязвимость межсайтового скриптинга, так как это дает кибератакующему способ совершить атаку.
Как правило, для этого типа атаки приложение должно многократно воспроизводить содержимое в ответах, чтобы кибератака может угадать ответ. Учитывая, как Blazor отрисовывается один раз, а затем создаёт диффы содержимого только для измененных элементов, это затрудняет действия кибератакера. Тем не менее, это не невозможно для киберзлоумышленника, поэтому необходимо принять меры предосторожности, чтобы избежать обработки конфиденциальной информации вместе с внешней информацией, которой может манипулировать киберзлоумышленник. Ниже приведены некоторые примеры.
Одновременная отрисовка персональных данных (PII) и данных из базы данных, добавленных другим пользователем, на странице.
Отображение информации о ПИИ на странице одновременно с данными, поступающими от другого пользователя через JS интероп или локальный одиночный сервис на сервере.
Как правило, мы рекомендуем избежать отрисовки компонентов, содержащих конфиденциальную информацию вместе с компонентами, которые могут отображать данные из ненадежных источников в рамках одного пакета отрисовки. Ненадежные источники включают параметры маршрута, строки запроса, данные из JS взаимодействия и любой другой источник данных, которые сторонний пользователь может контролировать (базы данных, внешние службы).
Общее состояние
Серверные Blazor приложения находятся в памяти сервера, и несколько сеансов одного приложения размещаются в одном процессе. Для каждого сеанса Blazor приложения запускает канал с собственной областью контейнера внедрения зависимостей, поэтому службы с областью действия уникальны для каждого Blazor сеанса.
Предупреждение
Не рекомендуется совместное использование состояния приложениями на одном сервере с помощью отдельных служб, если только вы не принимаете строгие меры предосторожности, поскольку при таком подходе могут возникать уязвимости, например утечка состояния пользователя между каналами.
Службы с отслеживанием состояния можно использовать в Blazor приложениях, если они специально разработаны для этого. Например, использование однотонного кэша памяти приемлемо, так как кэш памяти требует ключа для доступа к данной записи. Если у пользователей нет контроля над ключами кэша, которые используются с кэшем, состояние, хранящееся в кэше, не утечет между каналами.
Общие рекомендации по управлению состоянием см. в разделе ASP.NET Core Blazor State Management.
IHttpContextAccessor
/HttpContext
Для получения дополнительной информации см. IHttpContextAccessor/HttpContext в приложениях ASP.NET Core Blazor.
Нехватка ресурсов
Нехватка ресурсов может произойти, когда клиент взаимодействует с сервером и вынуждает сервер чрезмерно потреблять ресурсы. Чрезмерное потребление ресурсов в основном влияет на следующее:
Атаки типа "отказ в обслуживании" обычно стремятся исчерпать ресурсы приложения или сервера. Однако нехватка ресурсов не обязательно является результатом атаки на систему. Например, ограниченные ресурсы могут быть исчерпаны из-за высокой потребности пользователей. DoS рассматривается далее в разделе DoS.
Ресурсы, внешние по отношению к платформе Blazor, такие как базы данных и дескрипторы файлов (используемые для чтения и записи файлов), могут также испытывать нехватку ресурсов. Дополнительные сведения см. в разделе ASP.NET Основные рекомендации.
ЦП
Нехватка ресурсов ЦП может возникать, когда один или несколько клиентов вынуждают сервер интенсивно использовать ЦП.
Например, рассмотрим приложение, которое вычисляет число Fibonnacci. Число Фибоначчи формируется из последовательности Фибоначчи, где каждое число в последовательности является суммой двух предыдущих чисел. Объем работы, необходимый для получения результата, зависит от длины последовательности и размера начального значения. Если приложение не применяет ограничения для клиентских запросов, вычисления с интенсивным использованием ресурсов ЦП могут повлиять на время загрузки ЦП и уменьшить производительность выполнения других задач. Чрезмерное потребление ресурсов является проблемой безопасности, влияющей на доступность.
Нехватка ресурсов ЦП очень важна для всех общедоступных приложений. В обычных веб-приложениях время ожидания запросов и соединений является мерой защиты, но приложения Blazor не предоставляют такие же меры безопасности. Приложения Blazor должны включать соответствующие проверки и ограничения перед выполнением операций, которые могут потребовать значительных ресурсов ЦП.
Память
Нехватка памяти может возникать, когда один или несколько клиентов вынуждены принудительно использовать большой объем памяти.
Например, рассмотрим приложение с компонентом, принимаюющим и отображающим список элементов. Если приложение Blazor не устанавливает ограничения на количество допустимых элементов или число элементов, отрисовываемых для клиента, интенсивное использование памяти может стать настолько, что производительность сервера снизится. Сервер может аварийно завершить работу или замедлиться до сбоя.
Рассмотрим следующий сценарий хранения и отображения списка элементов, который приводит к потенциальной нехватке памяти на сервере:
- Элементы в свойстве или поле
List<T>
используют память сервера. Если приложение разрешает неограниченный рост списка элементов, существует риск нехватки памяти на сервере. При нехватке памяти текущий сеанс завершается (со сбоем), и все параллельные сеансы в этом экземпляре сервера получают исключение нехватки памяти. Чтобы предотвратить возникновение этого сценария, приложение должно использовать структуру данных, которая накладывает ограничение на число элементов для одновременно работающих пользователей. - Если для отрисовки не используется постраничная схема, сервер использует дополнительную память для объектов, которые не видны в пользовательском интерфейсе. При отсутствии ограничения на количество элементов запросы к памяти могут привести к исчерпанию доступной памяти сервера. Чтобы предотвратить этот сценарий, используйте один из следующих подходов:
- Используйте списки с разбивкой на страницы при визуализации.
- Отображайте только первые 100–1000 элементов и требуйте от пользователя ввести условия поиска для поиска элементов за пределами списка отображаемых элементов.
- Для более продвинутого сценария отрисовки реализуйте списки или сетки, поддерживающие виртуализацию. С помощью виртуализации в списках отображается только подмножество элементов, видимых пользователю. Когда пользователь взаимодействует с полосой прокрутки в пользовательском интерфейсе, компонент отображает только те элементы, которые требуются для отображения. Элементы, которые в данный момент не требуются для вывода, могут храниться во вторичном хранилище, что является идеальным подходом. Неотображаемые элементы также могут храниться в памяти, что менее эффективно.
Примечание.
Blazor имеет встроенную поддержку виртуализации. Дополнительные сведения см. в статье Виртуализация компонентов Razor ASP.NET Core.
Приложения Blazor предлагают аналогичную модель программирования для других платформ пользовательского интерфейса для приложений с отслеживанием состояния, таких как WPF, Windows Forms или Blazor WebAssembly. Основное отличие состоит в том, что в некоторых платформах пользовательского интерфейса объем памяти, потребляемой приложением, принадлежит клиенту и влияет только на этот клиент. Например, приложение Blazor WebAssembly выполняется полностью на клиенте и использует только ресурсы памяти клиента. Для серверного Blazor приложения память, потребляемая приложением, принадлежит серверу и предоставляется клиентам на экземпляре сервера.
Требования к памяти на стороне сервера являются важным фактором для всех серверных Blazor приложений. Однако большинство веб-приложений бездеятельны, и память, используемая при обработке запроса, освобождается при возврате ответа. В качестве общей рекомендации запретите клиентам выделять неограниченный объем памяти, как в любом другом серверном приложении, сохраняющем клиентские подключения. Память, потребляемая серверным Blazor приложением, сохраняется дольше, чем один запрос.
Примечание.
Во время разработки можно использовать профилировщик или выполнить трассировку для оценки объема памяти, необходимого клиентам. Профилировщик или трассировка не фиксируют память, выделенную для конкретного клиента. Чтобы зафиксировать использование памяти конкретным клиентом во время разработки, сделайте дамп памяти и изучите потребность в памяти всех объектов, исходящих из системы пользователя.
Клиентские подключения
Нехватка подключений может возникать, когда один или несколько клиентов открывают слишком много одновременных подключений к серверу, что блокирует установку новых подключений другими клиентами.
Клиенты Blazor устанавливают одно соединение на каждый сеанс и поддерживают его открытым, пока открыто окно браузера. Учитывая постоянный характер подключений и характер приложений Blazor на стороне сервера, исчерпание подключений является более серьезным риском для доступности приложения.
Количество подключений для каждого пользователя для приложения не ограничено. Если для приложения требуется ограничить количество подключений, воспользуйтесь одним или несколькими из следующих подходов.
- Требуйте проверку подлинности, которая естественным образом ограничивает возможность неавторизованных пользователей подключаться к приложению. Чтобы этот сценарий был эффективным, пользователям необходимо запретить подготовку новых пользователей по требованию.
- Ограничьте количество подключений для каждого пользователя. Ограничить количество подключений можно с помощью следующих подходов. Доступ к приложению следует предоставить только законным пользователям (например, если установлено ограничение на количество подключений на основе IP-адреса клиента).
- Уровень приложения
- Расширяемость маршрутизации конечных точек.
- Требуйте проверку подлинности для подключения к приложению и отслеживайте активные сеансы на пользователя.
- Отклоняйте новые сеансы при достижении ограничения.
- Используйте подключение WebSocket через прокси-сервер к приложению, например с помощью службы Azure SignalR, которая мультиплексирует подключения от клиентов к приложению. Это обеспечивает приложению более высокую производительность подключений, чем может обеспечить один клиент, что предотвращает исчерпание подключений клиента к серверу.
- Уровень сервера: перед приложением используйте прокси-сервер или шлюз.
- шлюз приложений Azure — это подсистема балансировки нагрузки веб-трафика (уровень 7 OSI), которая позволяет управлять трафиком в веб-приложения. Дополнительные сведения см. в разделе Обзор поддержки WebSocket в Шлюзе приложений.
- Azure Front Door — это служба балансировки нагрузки для распределения рабочих нагрузок между несколькими вычислительными ресурсами.
- Уровень приложения
- Требуйте проверку подлинности, которая естественным образом ограничивает возможность неавторизованных пользователей подключаться к приложению. Чтобы этот сценарий был эффективным, пользователям необходимо запретить подготовку новых пользователей по требованию.
- Ограничьте количество подключений для каждого пользователя. Ограничить количество подключений можно с помощью следующих подходов. Доступ к приложению следует предоставить только законным пользователям (например, если установлено ограничение на количество подключений на основе IP-адреса клиента).
- Уровень приложения
- Расширяемость маршрутизации конечных точек.
- Требуйте проверку подлинности для подключения к приложению и отслеживайте активные сеансы на пользователя.
- Отклоняйте новые сеансы при достижении ограничения.
- Используйте прокси-сервер для WebSocket-подключений к приложению, например, службу Azure SignalR, которая мультиплексирует подключения клиентов к приложению. Это обеспечивает приложению более высокую производительность подключений, чем может обеспечить один клиент, что предотвращает исчерпание подключений клиента к серверу.
- Уровень сервера
- Используйте прокси-сервер или шлюз для подключения к приложению.
- Хотя длинные опросы поддерживаются для приложений Blazor, в качестве транспортного протокола рекомендуется использовать WebSockets. Мы рекомендуем выбрать прокси-сервер или шлюз, поддерживающий WebSockets.
- Уровень приложения
Атаки типа "отказ в обслуживании" (DoS)
Атаки "Отказ в Обслуживании" (DoS) заключаются в том, что клиент заставляет сервер исчерпать один или несколько своих ресурсов, из-за чего приложение становится недоступным. Blazor приложения включают ограничения по умолчанию и полагаются на другие ASP.NET Core и SignalR ограничения, установленные CircuitOptions для защиты от атак DoS:
- CircuitOptions.DisconnectedCircuitMaxRetained
- CircuitOptions.DisconnectedCircuitRetentionPeriod
- CircuitOptions.JSInteropDefaultCallTimeout
- CircuitOptions.MaxBufferedUnacknowledgedRenderBatches
- HubConnectionContextOptions.MaximumReceiveMessageSize
Дополнительные сведения и примеры кода для настройки см. в следующих статьях:
Взаимодействие с браузером (клиент)
Клиент взаимодействует с сервером через диспетчеризацию событий интероперабельности JS и завершение рендеринга. Взаимодействие JS между JavaScript и .NET выполняется в обоих направлениях.
- События браузера отправляются с клиента на сервер асинхронным образом.
- Сервер отвечает асинхронно, при необходимости перерисовывает пользовательский интерфейс.
Функции JavaScript, вызываемые из .NET
Для вызовов из методов .NET к JavaScript:
- Все вызовы имеют настраиваемое время ожидания, по окончании которого они завершаются сбоем, возвращая OperationCanceledException вызывающей стороне.
- Время ожидания вызовов (CircuitOptions.JSInteropDefaultCallTimeout) по умолчанию — одна минута. Чтобы настроить это ограничение, см. статью Вызов функций JavaScript из методов .NET в ASP.NET Core Blazor.
- Для управления отменой для каждого вызова можно предусмотреть токен отмены. Ориентируйтесь на время ожидания вызова по умолчанию, когда это возможно, и ограничивайте по времени любой вызов клиента, если предоставлен токен отмены.
- Результату вызова JavaScript нельзя доверять. Клиент приложения Blazor, запущенный в браузере, выполняет поиск вызываемой функции JavaScript. Вызывается функция и создается либо результат, либо ошибка. Вредоносный клиент может попытаться:
- Вызывать проблемы в работе приложения, возвращая ошибку из функции JavaScript.
- Вызывать непреднамеренное поведение сервера, возвращая непредвиденный результат из функции JavaScript.
Выполните следующие меры предосторожности для защиты от предыдущих сценариев:
- Заключите вызовы взаимодействия JS в операторы
try-catch
, чтобы обрабатывать ошибки, которые могут возникнуть во время вызовов. Дополнительные сведения см. в статье Обработка ошибок в приложениях Blazor ASP.NET Core. - Перед выполнением следующих действий обязательно проверьте все данные, полученные вызовами взаимодействия JS, включая сообщения об ошибках.
Методы .NET, вызываемые из браузера
Не следует доверять вызовам из JavaScript к методам .NET. Когда метод .NET предоставляется JavaScript, рассмотрите способ вызова метода .NET:
- Рассматривайте любой метод .NET, экспортируемый в JavaScript, как публичную конечную точку вашего приложения.
- Проверьте входные данные.
- Убедитесь, что значения находятся в пределах ожидаемых диапазонов.
- Убедитесь, что у пользователя есть разрешение на выполнение запрошенного действия.
- Не выделяйте чрезмерное количество ресурсов в рамках вызова метода .NET. Например, выполните проверки и задайте ограничения на использование ресурсов ЦП и памяти.
- Примите во внимание, что статические методы и методы экземпляра могут предоставляться клиентам JavaScript. Избегайте совместного использования состояния между сеансами, если только проект не предусматривает общего использования состояния с соответствующими ограничениями.
- Для методов экземпляров, предоставляемых через объекты DotNetObjectReference, которые изначально были созданы с помощью внедрения зависимостей (DI), объекты должны быть зарегистрированы как объекты с областью действия. Это относится к любой службе DI, используемой приложением .
- Для статических методов избегайте установки состояния, которое не может быть ограничено клиентом, за исключением случаев, когда приложение по умолчанию предоставляет состояние для всех пользователей в экземпляре сервера.
- Старайтесь не передавать пользовательские данные в параметрах вызовов JavaScript. Если передача данных в параметрах является обязательной, убедитесь, что код JavaScript обеспечивает передачу данных без возникновения уязвимостей для межсайтовых сценариев (XSS). Например, не записывайте данные, предоставленные пользователем, в DOM, задав
innerHTML
свойство элемента. Для отключения и других ненадежных примитивов JavaScript рекомендуется использоватьeval
. Дополнительные сведения см. в разделе "Принуждение к применению политики безопасности содержимого для ASP.NET Core"Blazor и в руководстве CSP MDN.
- Проверьте входные данные.
- Избегайте реализации настраиваемой диспетчеризации вызовов .NET поверх реализации диспетчеризации платформы. Предоставление доступа к методам .NET для браузера является расширенным сценарием, не рекомендуемым для общих сценариев разработки Blazor.
События
События предоставляют точку входа приложению. Те же правила защиты конечных точек в веб-приложениях применяются к обработке событий в приложениях Blazor. Вредоносный клиент может отправить в качестве полезной нагрузки для события любые желаемые данные.
Например:
- Событие изменения для
<select>
может отправить значение, которое не находится в параметрах, представленных приложением для клиента. -
<input>
может отправить на сервер текстовые данные, минуя проверку на стороне клиента.
Приложение должно проверить данные для любого события, обрабатываемого приложением. Blazor фреймворк компоненты форм выполняют основные проверки. Если приложение использует настраиваемые компоненты форм, для проверки правильности данных событий необходимо написать пользовательский код.
События асинхронны, поэтому несколько событий можно отправлять на сервер до того, как приложение будет время реагировать, создав новую отрисовку. Это позволяет учитывать некоторые аспекты безопасности. Ограничение действий клиента в приложении должно производиться внутри обработчиков событий и не зависеть от отображенного состояния представления.
Рассмотрим компонент счетчика, который должен позволить пользователю увеличить значение счетчика не более трех раз. Кнопка для увеличения счетчика зависит от значения count
:
<p>Count: @count</p>
@if (count < 3)
{
<button @onclick="IncrementCount" value="Increment count" />
}
@code
{
private int count = 0;
private void IncrementCount()
{
count++;
}
}
Клиент может отправить одно или несколько событий приращения, прежде чем фреймворк выполнит новый рендеринг этого компонента. Таким образом, пользователь может увеличивать значение count
более чем три раза, поскольку кнопка не удаляется из пользовательского интерфейса достаточно быстро. Правильный способ достижения предельного значения в три приращения count
показан в следующем примере:
<p>Count: @count</p>
@if (count < 3)
{
<button @onclick="IncrementCount" value="Increment count" />
}
@code
{
private int count = 0;
private void IncrementCount()
{
if (count < 3)
{
count++;
}
}
}
При добавлении проверки if (count < 3) { ... }
внутри обработчика решение об увеличении count
зависит от текущего состояния приложения. Решение не зависит от состояния пользовательского интерфейса, которое было в предыдущем примере, что может быть временно устаревшим.
Защита от множественных отправлений
Если обратный вызов события вызывает длинную операцию асинхронно, например получение данных из внешней службы или базы данных, рассмотрите возможность использования защиты. Защита может запретить пользователю выполнять несколько операций, пока операция выполняется с помощью визуальной обратной связи. Следующий код компонента задает isLoading
для true
, пока DataService.GetDataAsync
получает данные с сервера. До тех пор, пока isLoading
имеет значение true
, кнопка отключена в пользовательском интерфейсе:
<button disabled="@isLoading" @onclick="UpdateData">Update</button>
@code {
private bool isLoading;
private Data[] data = Array.Empty<Data>();
private async Task UpdateData()
{
if (!isLoading)
{
isLoading = true;
data = await DataService.GetDataAsync(DateTime.Now);
isLoading = false;
}
}
}
Шаблон защиты, показанный в предыдущем примере, работает, если фоновая операция выполняется асинхронно с шаблоном async
-await
.
Отменяйте заранее, чтобы избежать ошибок "использования после удаления"
Помимо использования предохранителя, как описано в разделе "Защита от нескольких диспетчеров", рассмотрите возможность использования CancellationToken для отмены длительных операций при ликвидации компонента. Этот подход предоставляет дополнительные преимущества предотвращения use-after-dispose в компонентах:
@implements IDisposable
...
@code {
private readonly CancellationTokenSource TokenSource =
new CancellationTokenSource();
private async Task UpdateData()
{
...
data = await DataService.GetDataAsync(DateTime.Now, TokenSource.Token);
if (TokenSource.Token.IsCancellationRequested)
{
return;
}
...
}
public void Dispose()
{
TokenSource.Cancel();
}
}
Избегайте событий, создающих большие объемы данных
Некоторые события модели DOM, такие как oninput
или onscroll
, могут создавать большой объем данных. Избегайте использования этих событий на стороне сервера Blazor.
Дополнительные рекомендации по безопасности
Рекомендации по защите приложений ASP.NET Core применяются к серверным Blazor приложениям и рассматриваются в следующих разделах этой статьи:
- Ведение журнала и конфиденциальные данные
- Защита информации при передаче с помощью HTTPS
- Межсайтовые сценарии (XSS)
- Защита от атак из разных источников
- Кликджекинг
- Открытые перенаправления
Ведение журнала и конфиденциальные данные
Взаимодействия JS между клиентом и сервером сохраняются в журналы сервера с помощью экземпляров ILogger. Blazor предотвращает регистрацию конфиденциальной информации, например фактических событий, входных или выходных данных взаимодействия JS.
При возникновении ошибки на сервере платформа уведомляет клиента и разрывает сеанс. Клиент получает универсальное сообщение об ошибке, которое можно увидеть в средствах разработчика браузера.
Ошибка на стороне клиента не включает стек вызовов и не предоставляет сведения о причине ошибки, но журналы сервера содержат такие сведения. В целях разработки конфиденциальные сведения об ошибках можно сделать доступными для клиента, включив подробное описание ошибок.
Предупреждение
Предоставление сведений об ошибках клиентам в Интернете является угрозой безопасности, которую всегда следует избегать.
Защита информации при передаче с помощью HTTPS
Blazor использует SignalR для обмена данными между клиентом и сервером. Обычно Blazor использует транспорт, который согласовывает SignalR (чаще всего это WebSocket).
Blazor не гарантирует целостность и конфиденциальность данных, передаваемых между сервером и клиентом. Всегда используйте HTTPS.
Межсайтовые сценарии (XSS)
Межсайтовые сценарии (XSS) позволяют неавторизованной стороне выполнять произвольную логику в контексте браузера. Скомпрометированное приложение потенциально может выполнять произвольный код в клиенте. Уязвимость может быть использована для выполнения ряда вредоносных действий на сервере.
- Отправка фиктивных или недопустимых событий на сервер.
- Отказ отправки/неверные завершения операций рендеринга.
- Избегайте отправки завершения рендеринга.
- Отправка вызовов взаимодействия из JavaScript в .NET.
- Изменение ответа взаимодействующих вызовов из .NET в JavaScript.
- Избегайте отправки результатов взаимодействия .NET с JS.
Платформа Blazor обеспечивает защиту от некоторых из указанных ранее угроз:
- Прекращает создание новых обновлений пользовательского интерфейса, если клиент не подтверждает пакеты рендеринга. Настраивается с помощью CircuitOptions.MaxBufferedUnacknowledgedRenderBatches.
- Завершает время ожидания вызова .NET к JavaScript через одну минуту без получения ответа от клиента. Настраивается с помощью CircuitOptions.JSInteropDefaultCallTimeout.
- Выполняет базовую проверку всех входных данных, поступающих из браузера во время JS взаимодействия:
- Ссылки на .NET являются допустимыми и того типа, который ожидается методом .NET.
- Данные не искажены.
- В полезных данных содержится корректное число аргументов для метода.
- Аргументы или результат можно правильно десериализовать перед вызовом метода.
- Выполняет базовую проверку во всех входных данных, поступающих из браузера из отправленных событий:
- Событие имеет допустимый тип.
- Данные для события могут быть десериализованы.
- С событием связан обработчик событий.
В дополнение к средствам защиты, реализуемым платформой, приложение должно быть закодировано разработчиком для защиты от угроз и выполнения соответствующих действий:
- Всегда проверяйте данные при обработке событий.
- Выполните соответствующие действия при получении недопустимых данных:
- Игнорируйте данные и вернитесь. Это позволяет приложению продолжить обработку запросов.
- Если приложение определяет, что входные данные некорректные и не могут быть созданы законным клиентом, сгенерируйте исключение. Выброс исключения разрывает цепь и завершает сеанс.
- Не следует доверять сообщению об ошибке, предоставленному завершениями выполнения пакетов рендеринга, включенными в журналы. Ошибка предоставляется клиентом и, как правило, ей не стоит доверять, поскольку клиент может быть скомпрометирован.
- Не следует доверять входным данным JS при вызовах взаимодействия с обеих сторон между методами JavaScript и .NET.
- Приложение отвечает за проверку допустимости содержимого аргументов и результатов, даже если аргументы или результаты десериализованы правильно.
Чтобы существовала уязвимость XSS, приложение должно включать пользовательский ввод в отображённой странице. Blazor выполняет компиляционный шаг, при котором разметка в файле преобразуется в процедурную логику C#. Во время выполнения логика C# формирует дерево визуализации, описывающее элементы, текст и дочерние компоненты. Это применяется к модели DOM браузера через последовательность инструкций JavaScript (или сериализуется в HTML в случае предварительной отрисовки):
- Пользовательский ввод, отображаемый с помощью обычного синтаксиса Razor (например,
@someStringValue
), не предоставляет уязвимость XSS, так как синтаксис Razor добавляется в модель DOM с помощью команд, которые могут записывать только текст. Даже если значение включает HTML-разметку, значение отображается как статический текст. При предварительной отрисовке выходные данные кодируются в формате HTML, в результате чего содержимое отображается в виде статического текста. - Авторы компонентов могут создавать компоненты C# без использования Razor. Автор компонента несет ответственность за использование правильных API-интерфейсов при выдаче выходных данных. Например, используйте
builder.AddContent(0, someUserSuppliedString)
, а не не используйтеbuilder.AddMarkupContent(0, someUserSuppliedString)
, так как в последнем случае может возникнуть уязвимость XSS.
- Пользовательский ввод, отображаемый с помощью обычного синтаксиса Razor (например,
@someStringValue
), не предоставляет уязвимость XSS, так как синтаксис Razor добавляется в модель DOM с помощью команд, которые могут записывать только текст. Даже если значение включает HTML-разметку, значение отображается как статический текст. При предварительной отрисовке выходные данные кодируются в формате HTML, в результате чего содержимое отображается в виде статического текста. - Теги скриптов не допускаются и не должны включаться в дерево рендеринга компонента приложения. Если тег сценария включен в разметку компонента, создается ошибка времени компиляции.
- Авторы компонентов могут создавать компоненты C# без использования Razor. Автор компонента несет ответственность за использование правильных API-интерфейсов при выдаче выходных данных. Например, используйте
builder.AddContent(0, someUserSuppliedString)
и не используйтеbuilder.AddMarkupContent(0, someUserSuppliedString)
, так как впоследствии это может создать уязвимость XSS.
Рассмотрите возможность дальнейшего устранения уязвимостей XSS. Например, реализуйте ограничивающую политику безопасности содержимого (CSP). Дополнительные сведения см. в разделе "Принудительное применение политики безопасности содержимого для ASP.NET Core" Blazor и в руководстве по CSP на MDN.
Дополнительные сведения см. в разделе Предотвращение межсайтовых сценариев (XSS) в ASP.NET Core.
Защита от атак из разных источников
Атаки с использованием кросс-источников предполагают, что клиент из другого источника выполняет действие против сервера. Вредоносным действием обычно является запрос GET или форма POST (подделка межсайтовых запросов, CSRF), но также возможно открытие вредоносного WebSocket. Приложения Blazor предлагают те же гарантии, что и любое другое приложение SignalR, использующее протокол концентратора:
- Доступ к приложениям можно получить в разных источниках, если не приняты дополнительные меры, чтобы предотвратить его. Чтобы отключить доступ между разными источниками, выключите CORS в конечной точке, добавив промежуточное ПО CORS в конвейер и добавив DisableCorsAttribute в метаданные конечной точки Blazor, или ограничьте набор разрешенных источников, настраивая SignalR для совместного использования ресурсов между источниками. Рекомендации по ограничениям происхождения WebSocket см. в разделе "Поддержка WebSockets" в ASP.NET Core.
- Если CORS включен, для защиты приложения могут потребоваться дополнительные действия в зависимости от конфигурации CORS. Если вы включили CORS глобально, его можно отключить для концентратора BlazorSignalR, добавив метаданные DisableCorsAttribute в метаданные конечной точки после вызова MapBlazorHub в построителе маршрутов конечной точки.
Дополнительные сведения см. на странице Предотвращение атак с использованием подделки межсайтовых запросов (XSRF/CSRF) в ASP.NET Core.
Защита от взлома действия щелчка мышью
Кликджекинг включает встраивание сайта в качестве <iframe>
внутри сайта с другого домена, чтобы обмануть пользователя и заставить его выполнять действия на атакуемом сайте.
Чтобы защитить приложение от отображения внутри <iframe>
, используйте Политику безопасности контента (CSP) и заголовок X-Frame-Options
. Сведения о синтаксисе CSP см. в руководстве по CSP MDN.
Дополнительные сведения см. на следующих ресурсах:
- Принудительное применение политики безопасности содержимого для ASP.NET Core Blazor
- Веб-документация MDN: X-Frame-Options
Открытые перенаправления
При запуске сеанса приложения сервер выполняет базовую проверку URL-адресов, отправленных в рамках запуска сеанса. Платформа проверяет, является ли базовый URL-адрес родительским по отношению к текущему URL-адресу, прежде чем устанавливать канал. Платформа не выполняет никаких дополнительных проверок.
Когда пользователь выбирает ссылку в клиенте, URL-адрес ссылки отправляется на сервер, который определяет, какое действие следует предпринять. Например, приложение может выполнить навигацию на стороне клиента или указать браузеру, что необходимо перейти к новому расположению.
Компоненты также могут запускать запросы навигации программным способом с помощью NavigationManager. В таких случаях приложение может выполнить навигацию на стороне клиента или указать браузеру, что необходимо перейти к новому расположению.
Компоненты должны:
- Избегать использования входных данных пользователя в аргументах вызова навигации.
- Проверять аргументы, чтобы убедиться, что целевой объект разрешен приложением.
В противном случае злоумышленник может заставить браузер перейти на управляемый кибератакой сайт. В этом сценарии кибератакующий обманывает приложение, заставляя его использовать некоторые пользовательские входные данные при вызове метода NavigationManager.NavigateTo.
Этот совет также применим при отображении ссылок в рамках приложения.
- По возможности используйте относительные ссылки.
- Убедитесь, что ссылки на абсолютные адреса являются допустимыми, прежде чем включать их в страницу.
Дополнительные сведения см. в разделе Предотвращение атак с открытым перенаправлением в ASP.NET Core.
Контрольный список по безопасности
Следующий список вопросов безопасности не является исчерпывающим:
- Проверяйте аргументы из событий.
- Проверяйте входные данные и результаты вызовов межсистемного взаимодействия JS.
- Старайтесь не использовать (или заранее проверять) любой пользовательский ввод для вызовов из .NET к JS.
- Запретите клиенту выделять неограниченный объем памяти.
- Данные в компоненте.
- DotNetObjectReference объекты, возвращенные клиенту.
- Защита от нескольких отправок.
- Отменяйте длительные операции при удалении компонента.
- Избегайте событий, создающих большие объемы данных.
- Избегайте использования вводимых пользователем данных как часть вызовов NavigationManager.NavigateTo и сначала проверяйте вводимые пользователем данные для URL-адресов на соответствие набору разрешенных источников, если это неизбежно.
- Не принимайте решения об авторизации на основе состояния пользовательского интерфейса, только на основе состояния компонента.
- Для защиты от атак XSS рекомендуется использовать политики безопасности содержимого (CSP). Дополнительные сведения см. в разделе "Принудительное применение политики безопасности содержимого для ASP.NET Core"Blazor и в руководстве CSP от MDN.
- Рассмотрите возможность использования CSP и X-Frame-Options для защиты от кликджекинга.
- Убедитесь, что параметры CORS подходят при включении CORS, или явно отключите CORS для приложений Blazor.
- Убедитесь, что ограничения на стороне сервера для приложения Blazor обеспечивают приемлемое взаимодействие с пользователем без неприемлемых уровней риска.
ASP.NET Core