Руководство по устранению угроз для интерактивной отрисовки на стороне сервера ASP.NET Core Blazor

Примечание.

Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 8 этой статьи.

Внимание

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

В текущем выпуске см . версию .NET 8 этой статьи.

В этой статье объясняется, как устранять угрозы безопасности на интерактивной стороне Blazorсервера.

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

Когда пользователь посещает сайт , сервер создает канал в памяти сервера. Канал указывает браузеру, какое содержимое подготавливается к просмотру, и реагирует на события, например, когда пользователь нажимает кнопку в пользовательском интерфейсе. Для выполнения этих действий канал вызывает функции JavaScript в браузере пользователя и методах .NET на сервере. Это двустороннее взаимодействие на основе JavaScript называется взаимодействием с JavaScript (взаимодействием JS).

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

В ограниченных средах, например в корпоративных сетях или интрасетях, некоторые рекомендации по устранению рисков либо:

  • не применяются в ограниченной среде;
  • либо не стоят своих затрат на реализацию, поскольку в ограниченной среде угроза безопасности минимальна.

Интерактивные компоненты сервера с включенным сжатием WebSocket

Сжатие может предоставлять приложению атаки на стороне канала в отношении шифрования TLS подключения, таких как CRIME и BREACH атаки. Эти типы атак требуют, чтобы злоумышленник:

  • Принудительная браузеру выдавать запросы с полезными данными, которые злоумышленники контролируют уязвимый сайт через публикацию между сайтами или путем внедрения сайта в iframe другого сайта.
  • Просмотрите длину сжатого и зашифрованного ответа по сети.

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

Как правило, Blazor приложения могут включать сжатие по подключению WebSocket с соответствующими мерами безопасности:

  • Приложение может быть уязвимо, если оно принимает содержимое из запроса (например, путь или строка запроса), которое может влиять на злоумышленника и воспроизводит его в HTML-код страницы или в противном случае делает его частью ответа.

  • Blazor Применяет следующие меры безопасности автоматически:

    • При настройке Blazor сжатия автоматически блокирует внедрение приложения в iframe, который блокирует начальный (несжатый) ответ от сервера отрисовки и исключает подключение WebSocket когда-либо запуска.

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

  • Как правило, для этого типа атаки приложение должно многократно воспроизвести содержимое в ответах, чтобы злоумышленник смог угадать ответ. Учитывая способ Blazor отрисовки (он отрисовывает один раз, а затем создает диффы содержимого только для измененных элементов), это трудно сделать злоумышленнику. Однако злоумышленнику не удается сделать это так, чтобы избежать отрисовки конфиденциальной информации вместе с внешними данными, которые могут манипулировать злоумышленником. Ниже приведены некоторые примеры.

    • Отрисовка персональных данных (PII) на странице одновременно с данными базы данных отрисовки, добавленными другим пользователем.

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

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

Общее состояние

Серверные Blazor приложения живут в памяти сервера, а несколько сеансов приложений размещаются в одном процессе. Для каждого сеанса Blazor приложения запускает канал с собственным контейнером внедрения зависимостей область, поэтому область службы уникальны для Blazor каждого сеанса.

Предупреждение

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

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

Общие рекомендации по управлению состоянием см. в разделе ASP.NET Core Blazor State Management.

IHttpContextAccessor/HttpContext в Razor компонентах

IHttpContextAccessor необходимо избежать интерактивной отрисовки, так как не существует допустимой HttpContext возможности.

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

HttpContext можно использовать в качестве каскадного параметра только в статически отрисованных корневых компонентах для общих задач, таких как проверка и изменение заголовков или других свойств компонента App (Components/App.razor). Значение всегда null предназначено для интерактивной отрисовки.

[CascadingParameter]
public HttpContext? HttpContext { get; set; }

В сценариях, где HttpContext требуется в интерактивных компонентах, рекомендуется передавать данные через постоянное состояние компонента с сервера. Дополнительные сведения см . на стороне сервера ASP.NET Основных Blazor дополнительных сценариев безопасности.

Не используйте IHttpContextAccessor/HttpContext непосредственно или косвенно в Razor компонентах серверных Blazor приложений. Blazor приложения выполняются вне контекста конвейера ASP.NET Core. Он HttpContext не гарантируется, что он доступен в пределах приложения IHttpContextAccessorи HttpContext не гарантируется, что он будет содержать контекст, который запустил Blazor приложение.

Рекомендуемый подход для передачи состояния Blazor запроса приложению осуществляется через параметры корневого компонента во время первоначальной отрисовки приложения. Кроме того, приложение может скопировать данные в область службу в событии жизненного цикла инициализации корневого компонента для использования в приложении. Дополнительные сведения см . на стороне сервера ASP.NET Основных Blazor дополнительных сценариев безопасности.

Критически важный аспект безопасности на стороне Blazor сервера заключается в том, что пользователь, подключенный к заданному каналу, может быть обновлен в какой-то момент после Blazor установки канала, но IHttpContextAccessorне обновляется. Дополнительные сведения об устранении этой ситуации с пользовательскими службами см. в дополнительных сценариях безопасности на стороне сервера ASP.NET CoreBlazor.

Нехватка ресурсов

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

Атаки типа "отказ в обслуживании" обычно стремятся исчерпать ресурсы приложения или сервера. Однако нехватка ресурсов не обязательно является результатом атаки на систему. Например, ограниченные ресурсы могут быть исчерпаны из-за высокой потребности пользователей. 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 Front Door позволяет определять, управлять и отслеживать глобальную маршрутизацию веб-трафика в приложение и работать, когда приложения настроены для использования Long Polling.

      Примечание.

      Хотя длинный опрос поддерживается, WebSockets — это рекомендуемый транспортный протокол. По состоянию на февраль 2023 г. Azure Front Door не поддерживает WebSockets, но поддержка WebSockets находится в процессе разработки для будущего выпуска службы. Дополнительные сведения см. в статье "Поддержка подключений WebSocket" в Azure Front Door.

  • Требуйте проверку подлинности, которая естественным образом ограничивает возможность неавторизованных пользователей подключаться к приложению. Чтобы этот сценарий был эффективным, пользователям необходимо запретить подготовку новых пользователей по требованию.
  • Ограничьте количество подключений для каждого пользователя. Ограничить количество подключений можно с помощью следующих подходов. Доступ к приложению следует предоставить только законным пользователям (например, если установлено ограничение на количество подключений на основе IP-адреса клиента).
    • На уровне приложения:

      • Расширяемость маршрутизации конечных точек.
      • Требуйте проверку подлинности для подключения к приложению и отслеживайте активные сеансы на пользователя.
      • Отклоняйте новые сеансы при достижении ограничения.
      • Используйте прокси-сервер WebSocket для подключения к приложению, например службу Azure SignalR, которая мультиплексирует подключения от клиентов к приложению. Это обеспечивает приложению более высокую производительность подключений, чем может обеспечить один клиент, что предотвращает исчерпание подключений клиента к серверу.
    • На уровне сервера: используйте прокси-сервер или шлюз перед приложением.

      Примечание.

      Хотя длинный опрос поддерживается, WebSockets — это рекомендуемый транспортный протокол.

Атаки типа "отказ в обслуживании" (DoS)

Атаки типа "отказ в обслуживании" включают клиента, вызывающего сервер исчерпание одного или нескольких его ресурсов, что делает приложение недоступным. Blazor приложения включают ограничения по умолчанию и полагаются на другие ASP.NET Core и SignalR ограничения, установленные CircuitOptions для защиты от атак DoS:

Дополнительные сведения и примеры кода для настройки см. в следующих статьях:

Взаимодействие с браузером (клиент)

Клиент взаимодействует с сервером через событие взаимодействия 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 свойство элемента. Для отключения eval и других ненадежных примитивов JavaScript рекомендуется использовать политики безопасности содержимого (CSP). Дополнительные сведения см. в разделе "Принудительное применение политики безопасности содержимого" для ASP.NET Core Blazor.
  • Избегайте реализации настраиваемой диспетчеризации вызовов .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;
        }
    }
}

Защита, показанная в предыдущем примере, работает, если фоновая операция выполняется асинхронно с шаблоном asyncawait-.

Отмена в начале и избежание use-after-dispose

Помимо использования защиты, как описано в разделе Защита от нескольких отправок, рассмотрите возможность использования 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 приложениям и рассматриваются в следующих разделах этой статьи:

Ведение журнала и конфиденциальные данные

Взаимодействия 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 выполняет шаг во время компиляции, в котором разметка в файле преобразуется в .razor процедурную логику C#. Во время выполнения C# логика создает дерево преобразования для просмотра, описывающее элементы, текст и дочерние компоненты. Это применяется к модели DOM браузера через последовательность инструкций JavaScript (или сериализуется в HTML в случае предварительного преобразования для просмотра):

  • Пользовательский ввод, отображаемый с помощью обычного синтаксиса 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.

Дополнительные сведения см. в разделе Предотвращение межсайтовых сценариев (XSS) в ASP.NET Core.

Защита от атак из разных источников

Атаки с использованием разных источников предполагают, что клиент из другого источника выполняет действие с сервером. Вредоносным действием обычно является запрос GET или форма POST (подделка межсайтовых запросов, CSRF), но также возможно открытие вредоносного WebSocket. Приложения Blazor предлагают те же гарантии, что и любое другое приложение SignalR, использующее протокол концентратора:

  • Доступ к приложениям можно получить в разных источниках, если не приняты дополнительные меры, чтобы предотвратить его. Чтобы отключить доступ между источниками, отключите CORS в конечной точке, добавив ПО промежуточного слоя CORS в конвейер и добавив DisableCorsAttributeBlazor метаданные конечной точки или ограничить набор разрешенных источников, настроив SignalR для общего доступа к ресурсам между источниками. Рекомендации по ограничениям происхождения WebSocket см. в разделе "Поддержка WebSockets" в ASP.NET Core.
  • Если CORS включен, для защиты приложения могут потребоваться дополнительные действия в зависимости от конфигурации CORS. Если вы включили CORS глобально, его можно отключить для концентратора BlazorSignalR, добавив метаданные DisableCorsAttribute в метаданные конечной точки после вызова MapBlazorHub в построителе маршрутов конечной точки.

Дополнительные сведения см. на странице Предотвращение атак с использованием подделки межсайтовых запросов (XSRF/CSRF) в ASP.NET Core.

Защита от взлома действия щелчка мышью

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

Чтобы защитить приложение от преобразования для просмотра в <iframe>, используйте политики безопасности содержимого (CSP) и заголовок 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 и X-Frame-Options для защиты от взлома действия щелчка мышью.
  • Убедитесь, что параметры CORS подходят при включении CORS, или явно отключите CORS для приложений Blazor.
  • Убедитесь, что ограничения на стороне сервера для приложения Blazor обеспечивают приемлемое взаимодействие с пользователем без неприемлемых уровней риска.