Proteger ASP.NET Core aplicativos do Blazor ServerSecure ASP.NET Core Blazor Server apps

Por Javier Calvarro NelsonBy Javier Calvarro Nelson

os aplicativos do Blazor Server adotam um modelo de processamento de dados com estado , onde o servidor e o cliente mantêm uma relação de vida longa.Blazor Server apps adopt a stateful data processing model, where the server and client maintain a long-lived relationship. O estado persistente é mantido por um circuito, que pode abranger conexões que também são potencialmente de longa duração.The persistent state is maintained by a circuit, which can span connections that are also potentially long-lived.

Quando um usuário visita um site do Blazor Server, o servidor cria um circuito na memória do servidor.When a user visits a Blazor Server site, the server creates a circuit in the server's memory. O circuito indica ao navegador qual conteúdo renderizar e responde a eventos, como quando o usuário seleciona um botão na interface do usuário.The circuit indicates to the browser what content to render and responds to events, such as when the user selects a button in the UI. Para executar essas ações, um circuito invoca funções JavaScript no navegador do usuário e nos métodos do .NET no servidor.To perform these actions, a circuit invokes JavaScript functions in the user's browser and .NET methods on the server. Essa interação baseada em JavaScript bidirecional é conhecida como interoperabilidade JavaScript (JS Interop).This two-way JavaScript-based interaction is referred to as JavaScript interop (JS interop).

Como a interoperabilidade do JS ocorre pela Internet e o cliente usa um navegador remoto, os aplicativos do Blazor Server compartilham a maioria das preocupações de segurança do aplicativo Web.Because JS interop occurs over the Internet and the client uses a remote browser, Blazor Server apps share most web app security concerns. Este tópico descreve as ameaças comuns a aplicativos Blazor Server e fornece diretrizes de mitigação de ameaças voltadas para aplicativos voltados para a Internet.This topic describes common threats to Blazor Server apps and provides threat mitigation guidance focused on Internet-facing apps.

Em ambientes restritos, como dentro de redes corporativas ou intranets, algumas das diretrizes de mitigação:In constrained environments, such as inside corporate networks or intranets, some of the mitigation guidance either:

  • Não se aplica ao ambiente restrito.Doesn't apply in the constrained environment.
  • Não vale o custo para implementar porque o risco de segurança está baixo em um ambiente restrito.Isn't worth the cost to implement because the security risk is low in a constrained environment.

Esgotamento de recursosResource exhaustion

O esgotamento de recursos pode ocorrer quando um cliente interage com o servidor e faz com que o servidor consuma recursos excessivos.Resource exhaustion can occur when a client interacts with the server and causes the server to consume excessive resources. O consumo excessivo de recursos afeta principalmente:Excessive resource consumption primarily affects:

Ataques de DoS (negação de serviço) geralmente buscam esgotar os recursos de um aplicativo ou servidor.Denial of service (DoS) attacks usually seek to exhaust an app or server's resources. No entanto, o esgotamento de recursos não é necessariamente o resultado de um ataque no sistema.However, resource exhaustion isn't necessarily the result of an attack on the system. Por exemplo, recursos finitos podem ser esgotados devido à alta demanda do usuário.For example, finite resources can be exhausted due to high user demand. O DoS é abordado mais detalhadamente na seção ataques dos (negação de serviço) .DoS is covered further in the Denial of service (DoS) attacks section.

Recursos externos à estrutura de Blazor, como bancos de dados e identificadores de arquivo (usados para ler e gravar arquivos), também podem ter esgotamento de recursos.Resources external to the Blazor framework, such as databases and file handles (used to read and write files), may also experience resource exhaustion. Para obter mais informações, consulte Práticas recomendadas de desempenho de ASP.NET Core.For more information, see Práticas recomendadas de desempenho de ASP.NET Core.

CPUCPU

O esgotamento de CPU pode ocorrer quando um ou mais clientes forçam o servidor a executar um trabalho intensivo de CPU.CPU exhaustion can occur when one or more clients force the server to perform intensive CPU work.

Por exemplo, considere um aplicativo de servidor Blazor que calcula um número Fibonnacci.For example, consider a Blazor Server app that calculates a Fibonnacci number. Um número Fibonnacci é produzido de uma sequência Fibonnacci, em que cada número na sequência é a soma dos dois números anteriores.A Fibonnacci number is produced from a Fibonnacci sequence, where each number in the sequence is the sum of the two preceding numbers. A quantidade de trabalho necessária para alcançar a resposta depende do comprimento da sequência e do tamanho do valor inicial.The amount of work required to reach the answer depends on the length of the sequence and the size of the initial value. Se o aplicativo não coloca limites na solicitação de um cliente, os cálculos com uso intensivo de CPU podem dominar o tempo da CPU e diminuir o desempenho de outras tarefas.If the app doesn't place limits on a client's request, the CPU-intensive calculations may dominate the CPU's time and diminish the performance of other tasks. O consumo excessivo de recursos é uma preocupação de segurança que afeta a disponibilidade.Excessive resource consumption is a security concern impacting availability.

O esgotamento da CPU é uma preocupação para todos os aplicativos voltados ao público.CPU exhaustion is a concern for all public-facing apps. Em aplicativos Web regulares, solicitações e conexões atingiram o tempo limite como uma proteção, mas os aplicativos do Blazor Server não fornecem as mesmas proteções.In regular web apps, requests and connections time out as a safeguard, but Blazor Server apps don't provide the same safeguards. os aplicativos do Blazor Server devem incluir verificações e limites apropriados antes de executar um trabalho potencialmente intensivo de CPU.Blazor Server apps must include appropriate checks and limits before performing potentially CPU-intensive work.

MemóriaMemory

O esgotamento de memória pode ocorrer quando um ou mais clientes forçam o servidor a consumir uma grande quantidade de memória.Memory exhaustion can occur when one or more clients force the server to consume a large amount of memory.

Por exemplo, considere um aplicativo do lado do BlazorServer com um componente que aceita e exibe uma lista de itens.For example, consider a Blazor-server side app with a component that accepts and displays a list of items. Se o aplicativo Blazor não coloca limites no número de itens permitidos ou no número de itens processados de volta para o cliente, o processamento e a renderização com uso intensivo de memória podem dominar a memória do servidor até o ponto em que o desempenho do servidor sofre.If the Blazor app doesn't place limits on the number of items allowed or the number of items rendered back to the client, the memory-intensive processing and rendering may dominate the server's memory to the point where performance of the server suffers. O servidor pode falhar ou ficar lento até o ponto em que parece ter falhado.The server may crash or slow to the point that it appears to have crashed.

Considere o cenário a seguir para manter e exibir uma lista de itens que pertencem a um possível cenário de esgotamento de memória no servidor:Consider the following scenario for maintaining and displaying a list of items that pertain to a potential memory exhaustion scenario on the server:

  • Os itens em uma List<MyItem> propriedade ou campo usam a memória do servidor.The items in a List<MyItem> property or field use the server's memory. Se o aplicativo permitir que a lista de itens cresça sem limites, haverá um risco de que o servidor fique com memória insuficiente.If the app allows the list of items to grow unbounded, there's a risk of the server running out of memory. A execução de memória insuficiente faz com que a sessão atual seja encerrada (falha) e todas as sessões simultâneas nessa instância do servidor recebam uma exceção de memória insuficiente.Running out of memory causes the current session to end (crash) and all of the concurrent sessions in that server instance receive an out-of-memory exception. Para evitar que esse cenário ocorra, o aplicativo deve usar uma estrutura de dados que impõe um limite de item em usuários simultâneos.To prevent this scenario from occurring, the app must use a data structure that imposes an item limit on concurrent users.
  • Se um esquema de paginação não for usado para renderização, o servidor usará memória adicional para objetos que não estão visíveis na interface do usuário.If a paging scheme isn't used for rendering, the server uses additional memory for objects that aren't visible in the UI. Sem um limite para o número de itens, as demandas de memória podem esgotar a memória disponível do servidor.Without a limit on the number of items, memory demands may exhaust the available server memory. Para evitar esse cenário, use uma das seguintes abordagens:To prevent this scenario, use one of the following approaches:
    • Use listas paginadas ao renderizar.Use paginated lists when rendering.
    • Exiba apenas os primeiros 100 a 1.000 itens e exija que o usuário insira critérios de pesquisa para localizar itens além dos itens exibidos.Only display the first 100 to 1,000 items and require the user to enter search criteria to find items beyond the items displayed.
    • Para um cenário de renderização mais avançado, implemente listas ou grades que dão suporte à virtualização.For a more advanced rendering scenario, implement lists or grids that support virtualization. Usando a virtualização, as listas só renderizam um subconjunto de itens visíveis no momento para o usuário.Using virtualization, lists only render a subset of items currently visible to the user. Quando o usuário interage com a barra de rolagem na interface do usuário, o componente renderiza somente os itens necessários para exibição.When the user interacts with the scrollbar in the UI, the component renders only those items required for display. Os itens que atualmente não são necessários para exibição podem ser mantidos no armazenamento secundário, que é a abordagem ideal.The items that aren't currently required for display can be held in secondary storage, which is the ideal approach. Itens não exibidos também podem ser mantidos na memória, o que é menos ideal.Undisplayed items can also be held in memory, which is less ideal.

os aplicativos do Blazor Server oferecem um modelo de programação semelhante a outras estruturas de interface do usuário para aplicativos com estado, como WPF, Windows Forms ou Blazor Webassembly.Blazor Server apps offer a similar programming model to other UI frameworks for stateful apps, such as WPF, Windows Forms, or Blazor WebAssembly. A principal diferença é que, em várias das estruturas da interface do usuário, a memória consumida pelo aplicativo pertence ao cliente e afeta apenas esse cliente individual.The main difference is that in several of the UI frameworks the memory consumed by the app belongs to the client and only affects that individual client. Por exemplo, um aplicativo Webassembly Blazor é executado inteiramente no cliente e usa apenas recursos de memória do cliente.For example, a Blazor WebAssembly app runs entirely on the client and only uses client memory resources. No cenário do Blazor Server, a memória consumida pelo aplicativo pertence ao servidor e é compartilhada entre clientes na instância do servidor.In the Blazor Server scenario, the memory consumed by the app belongs to the server and is shared among clients on the server instance.

As demandas de memória do lado do servidor são uma consideração para todos os aplicativos do Blazor Server.Server-side memory demands are a consideration for all Blazor Server apps. No entanto, a maioria dos aplicativos Web não tem estado e a memória usada durante o processamento de uma solicitação é liberada quando a resposta é retornada.However, most web apps are stateless, and the memory used while processing a request is released when the response is returned. Como recomendação geral, não permita que os clientes aloquem uma quantidade não associada de memória como em qualquer outro aplicativo do lado do servidor que persista as conexões do cliente.As a general recommendation, don't permit clients to allocate an unbound amount of memory as in any other server-side app that persists client connections. A memória consumida por um aplicativo do Blazor Server persiste por mais tempo do que uma única solicitação.The memory consumed by a Blazor Server app persists for a longer time than a single request.

Observação

Durante o desenvolvimento, um criador de perfil pode ser usado ou um rastreamento capturado para avaliar as demandas de memória dos clientes.During development, a profiler can be used or a trace captured to assess memory demands of clients. Um criador de perfil ou rastreamento não capturará a memória alocada para um cliente específico.A profiler or trace won't capture the memory allocated to a specific client. Para capturar o uso de memória de um cliente específico durante o desenvolvimento, Capture um despejo e examine a demanda de memória de todos os objetos com raiz no circuito do usuário.To capture the memory use of a specific client during development, capture a dump and examine the memory demand of all the objects rooted at a user's circuit.

Conexões de clientesClient connections

O esgotamento de conexão pode ocorrer quando um ou mais clientes abrem muitas conexões simultâneas com o servidor, impedindo que outros clientes estabeleçam novas conexões.Connection exhaustion can occur when one or more clients open too many concurrent connections to the server, preventing other clients from establishing new connections.

Blazor clientes estabelecem uma única conexão por sessão e mantêm a conexão aberta enquanto a janela do navegador está aberta. clients establish a single connection per session and keep the connection open for as long as the browser window is open. As demandas no servidor de manutenção de todas as conexões não são específicas para Blazor aplicativos.The demands on the server of maintaining all of the connections isn't specific to Blazor apps. Considerando a natureza persistente das conexões e a natureza com estado dos aplicativos do Blazor Server, o esgotamento da conexão é um risco maior à disponibilidade do aplicativo.Given the persistent nature of the connections and the stateful nature of Blazor Server apps, connection exhaustion is a greater risk to availability of the app.

Por padrão, não há limite para o número de conexões por usuário para um aplicativo de Blazor Server.By default, there's no limit on the number of connections per user for a Blazor Server app. Se o aplicativo exigir um limite de conexão, execute uma ou mais das seguintes abordagens:If the app requires a connection limit, take one or more of the following approaches:

  • Exigir autenticação, o que limita naturalmente a capacidade de usuários não autorizados se conectarem ao aplicativo.Require authentication, which naturally limits the ability of unauthorized users to connect to the app. Para que esse cenário seja eficaz, os usuários devem ser impedidos de provisionar novos usuários no.For this scenario to be effective, users must be prevented from provisioning new users at will.
  • Limite o número de conexões por usuário.Limit the number of connections per user. A limitação de conexões pode ser realizada por meio das abordagens a seguir.Limiting connections can be accomplished via the following approaches. Tome cuidado para permitir que usuários legítimos acessem o aplicativo (por exemplo, quando um limite de conexão é estabelecido com base no endereço IP do cliente).Exercise care to allow legitimate users to access the app (for example, when a connection limit is established based on the client's IP address).
    • No nível do aplicativo:At the app level:
      • Extensibilidade de roteamento de ponto de extremidade.Endpoint routing extensibility.
      • Exigir autenticação para se conectar ao aplicativo e controlar as sessões ativas por usuário.Require authentication to connect to the app and keep track of the active sessions per user.
      • Rejeite novas sessões após atingir um limite.Reject new sessions upon reaching a limit.
      • Conexões de WebSocket de proxy para um aplicativo por meio do uso de um proxy, como o serviço de SignalR do Azure que multiplexa conexões de clientes para um aplicativo.Proxy WebSocket connections to an app through the use of a proxy, such as the Azure SignalR Service that multiplexes connections from clients to an app. Isso fornece um aplicativo com maior capacidade de conexão do que um único cliente pode estabelecer, impedindo que um cliente esgotasse as conexões com o servidor.This provides an app with greater connection capacity than a single client can establish, preventing a client from exhausting the connections to the server.
    • No nível do servidor: Use um proxy/gateway na frente do aplicativo.At the server level: Use a proxy/gateway in front of the app. Por exemplo, a porta frontal do Azure permite que você defina, gerencie e monitore o roteamento global do tráfego da Web para um aplicativo.For example, Azure Front Door enables you to define, manage, and monitor the global routing of web traffic to an app.

Ataques de negação de serviço (DoS)Denial of service (DoS) attacks

Ataques de DoS (negação de serviço) envolvem um cliente que está fazendo com que o servidor esgotasse um ou mais de seus recursos, tornando o aplicativo indisponível.Denial of service (DoS) attacks involve a client causing the server to exhaust one or more of its resources making the app unavailable. os aplicativos do Blazor Server incluem alguns limites padrão e contam com outros limites de ASP.NET Core e SignalR para proteger contra ataques de DoS:Blazor Server apps include some default limits and rely on other ASP.NET Core and SignalR limits to protect against DoS attacks:

limite de aplicativo do Blazor ServerBlazor Server app limit DescriçãoDescription PadrãoDefault
CircuitOptions.DisconnectedCircuitMaxRetained Número máximo de circuitos desconectados que um determinado servidor mantém na memória por vez.Maximum number of disconnected circuits that a given server holds in memory at a time. 100100
CircuitOptions.DisconnectedCircuitRetentionPeriod Quantidade máxima de tempo que um circuito desconectado é mantido na memória antes de ser interrompido.Maximum amount of time a disconnected circuit is held in memory before being torn down. Três minutos3 minutes
CircuitOptions.JSInteropDefaultCallTimeout Quantidade máxima de tempo que o servidor espera antes de atingir o tempo limite de uma invocação de função JavaScript assíncrona.Maximum amount of time the server waits before timing out an asynchronous JavaScript function invocation. 1 minuto1 minute
CircuitOptions.MaxBufferedUnacknowledgedRenderBatches Número máximo de lotes de renderização não confirmados que o servidor mantém na memória por circuito em um determinado momento para dar suporte à reconexão robusta.Maximum number of unacknowledged render batches the server keeps in memory per circuit at a given time to support robust reconnection. Depois de atingir o limite, o servidor para de produzir novos lotes de renderização até que um ou mais lotes tenham sido confirmados pelo cliente.After reaching the limit, the server stops producing new render batches until one or more batches have been acknowledged by the client. 1010
limite de SignalR e ASP.NET CoreSignalR and ASP.NET Core limit DescriçãoDescription PadrãoDefault
CircuitOptions.MaximumReceiveMessageSize Tamanho da mensagem para uma mensagem individual.Message size for an individual message. 32 KB32 KB

Interações com o navegador (cliente)Interactions with the browser (client)

Um cliente interage com o servidor por meio de expedição de evento de interoperabilidade do JS e conclusão do processamento.A client interacts with the server through JS interop event dispatching and render completion. A comunicação de interoperabilidade do JS é de ambas as maneiras entre JavaScript e .NET:JS interop communication goes both ways between JavaScript and .NET:

  • Os eventos de navegador são expedidos do cliente para o servidor de maneira assíncrona.Browser events are dispatched from the client to the server in an asynchronous fashion.
  • O servidor responde de forma assíncrona reprocessando a interface do usuário conforme necessário.The server responds asynchronously rerendering the UI as necessary.

Funções JavaScript invocadas do .NETJavaScript functions invoked from .NET

Para chamadas de métodos .NET para JavaScript:For calls from .NET methods to JavaScript:

  • Todas as invocações têm um tempo limite configurável após o qual falham, retornando um OperationCanceledException ao chamador.All invocations have a configurable timeout after which they fail, returning a OperationCanceledException to the caller.
    • Há um tempo limite padrão para as chamadas (CircuitOptions.JSInteropDefaultCallTimeout) de um minuto.There's a default timeout for the calls (CircuitOptions.JSInteropDefaultCallTimeout) of one minute. Para configurar esse limite, consulte ASP.NET Core interoperabilidade Blazor JavaScript.To configure this limit, see ASP.NET Core interoperabilidade Blazor JavaScript.
    • Um token de cancelamento pode ser fornecido para controlar o cancelamento em uma base por chamada.A cancellation token can be provided to control the cancellation on a per-call basis. Conte com o tempo limite de chamada padrão quando possível e Associação de tempo qualquer chamada ao cliente se um token de cancelamento for fornecido.Rely on the default call timeout where possible and time-bound any call to the client if a cancellation token is provided.
  • O resultado de uma chamada JavaScript não pode ser confiável.The result of a JavaScript call can't be trusted. O cliente de aplicativo Blazor em execução no navegador pesquisa a função JavaScript a ser invocada.The Blazor app client running in the browser searches for the JavaScript function to invoke. A função é invocada e o resultado ou um erro é produzido.The function is invoked, and either the result or an error is produced. Um cliente mal-intencionado pode tentar:A malicious client can attempt to:
    • Causar um problema no aplicativo retornando um erro da função JavaScript.Cause an issue in the app by returning an error from the JavaScript function.
    • Induzir um comportamento indesejado no servidor retornando um resultado inesperado da função JavaScript.Induce an unintended behavior on the server by returning an unexpected result from the JavaScript function.

Tome as seguintes precauções para proteger contra os cenários anteriores:Take the following precautions to guard against the preceding scenarios:

  • Encapsular chamadas de interoperabilidade JS em instruções try-catch para considerar erros que podem ocorrer durante as invocações.Wrap JS interop calls within try-catch statements to account for errors that might occur during the invocations. Para obter mais informações, consulte Tratar erros em aplicativos ASP.NET Core Blazor.For more information, see Tratar erros em aplicativos ASP.NET Core Blazor.
  • Valide os dados retornados das invocações de interoperabilidade do JS, incluindo mensagens de erro, antes de realizar qualquer ação.Validate data returned from JS interop invocations, including error messages, before taking any action.

Métodos .NET invocados no navegador.NET methods invoked from the browser

Não confie em chamadas de JavaScript para métodos .NET.Don't trust calls from JavaScript to .NET methods. Quando um método .NET é exposto ao JavaScript, considere como o método .NET é invocado:When a .NET method is exposed to JavaScript, consider how the .NET method is invoked:

  • Trate qualquer método .NET exposto ao JavaScript como você faria com um ponto de extremidade público para o aplicativo.Treat any .NET method exposed to JavaScript as you would a public endpoint to the app.
    • Validar entrada.Validate input.
      • Verifique se os valores estão dentro dos intervalos esperados.Ensure that values are within expected ranges.
      • Verifique se o usuário tem permissão para executar a ação solicitada.Ensure that the user has permission to perform the action requested.
    • Não aloque uma quantidade excessiva de recursos como parte da invocação do método .NET.Don't allocate an excessive quantity of resources as part of the .NET method invocation. Por exemplo, execute verificações e coloque limites no uso de CPU e memória.For example, perform checks and place limits on CPU and memory use.
    • Leve em consideração que os métodos estáticos e de instância podem ser expostos a clientes JavaScript.Take into account that static and instance methods can be exposed to JavaScript clients. Evite compartilhar o estado entre as sessões, a menos que o design chame o estado de compartilhamento com as restrições apropriadas.Avoid sharing state across sessions unless the design calls for sharing state with appropriate constraints.
      • Para métodos de instância expostos por meio de DotNetReference objetos criados originalmente por meio de injeção de dependência (DI), os objetos devem ser registrados como objetos com escopo.For instance methods exposed through DotNetReference objects that are originally created through dependency injection (DI), the objects should be registered as scoped objects. Isso se aplica a qualquer serviço de DI que o aplicativo do Blazor Server use.This applies to any DI service that the Blazor Server app uses.
      • Para métodos estáticos, evite estabelecer o estado que não pode ser definido como escopo para o cliente, a menos que o aplicativo esteja explicitamente compartilhando o estado por design em todos os usuários em uma instância de servidor.For static methods, avoid establishing state that can't be scoped to the client unless the app is explicitly sharing state by-design across all users on a server instance.
    • Evite passar dados fornecidos pelo usuário em parâmetros para chamadas JavaScript.Avoid passing user-supplied data in parameters to JavaScript calls. Se a passagem de dados em parâmetros for absolutamente necessária, verifique se o código JavaScript lida com a passagem dos dados sem introduzir vulnerabilidades de XSS (script entre sites) .If passing data in parameters is absolutely required, ensure that the JavaScript code handles passing the data without introducing Cross-site scripting (XSS) vulnerabilities. Por exemplo, não grave dados fornecidos pelo usuário no Modelo de Objeto do Documento (DOM) definindo a propriedade innerHTML de um elemento.For example, don't write user-supplied data to the Document Object Model (DOM) by setting the innerHTML property of an element. Considere o uso da política de segurança de conteúdo (CSP) para desabilitar eval e outros primitivos JavaScript não seguros.Consider using Content Security Policy (CSP) to disable eval and other unsafe JavaScript primitives.
  • Evite implementar a expedição personalizada de invocações do .NET sobre a implementação de expedição da estrutura.Avoid implementing custom dispatching of .NET invocations on top of the framework's dispatching implementation. Expor métodos .NET ao navegador é um cenário avançado, não recomendado para desenvolvimento de Blazor geral.Exposing .NET methods to the browser is an advanced scenario, not recommended for general Blazor development.

EventsEvents

Os eventos fornecem um ponto de entrada para um aplicativo do Blazor Server.Events provide an entry point to a Blazor Server app. As mesmas regras para proteger pontos de extremidade em aplicativos Web se aplicam à manipulação de eventos em aplicativos do Blazor Server.The same rules for safeguarding endpoints in web apps apply to event handling in Blazor Server apps. Um cliente mal-intencionado pode enviar todos os dados que deseja enviar como a carga de um evento.A malicious client can send any data it wishes to send as the payload for an event.

Por exemplo:For example:

  • Um evento de alteração para um <select> pode enviar um valor que não está dentro das opções que o aplicativo apresentou ao cliente.A change event for a <select> could send a value that isn't within the options that the app presented to the client.
  • Um <input> pode enviar qualquer dado de texto para o servidor, ignorando a validação do lado do cliente.An <input> could send any text data to the server, bypassing client-side validation.

O aplicativo deve validar os dados para qualquer evento que o aplicativo manipular.The app must validate the data for any event that the app handles. Os componentes do Blazor Framework Forms executam validações básicas.The Blazor framework forms components perform basic validations. Se o aplicativo usar componentes de formulários personalizados, o código personalizado deverá ser escrito para validar os dados de evento conforme apropriado.If the app uses custom forms components, custom code must be written to validate event data as appropriate.

os eventos do Blazor Server são assíncronos, de modo que vários eventos podem ser expedidos para o servidor antes que o aplicativo tenha tempo de reagir, produzindo um novo processamento.Blazor Server events are asynchronous, so multiple events can be dispatched to the server before the app has time to react by producing a new render. Isso tem algumas implicações de segurança a serem consideradas.This has some security implications to consider. A limitação de ações do cliente no aplicativo deve ser executada dentro de manipuladores de eventos e não depende do estado atual da exibição renderizada.Limiting client actions in the app must be performed inside event handlers and not depend on the current rendered view state.

Considere um componente de contador que deve permitir que um usuário aumente um contador no máximo três vezes.Consider a counter component that should allow a user to increment a counter a maximum of three times. O botão para incrementar o contador é condicionalmente baseado no valor de count:The button to increment the counter is conditionally based on the value of count:

<p>Count: @count<p>

@if (count < 3)
{
    <button @onclick="IncrementCount" value="Increment count" />
}

@code 
{
    private int count = 0;

    private void IncrementCount()
    {
        count++;
    }
}

Um cliente pode enviar um ou mais eventos de incremento antes que a estrutura produza um novo processamento desse componente.A client can dispatch one or more increment events before the framework produces a new render of this component. O resultado é que o count pode ser incrementado em três vezes pelo usuário, pois o botão não é removido pela interface de usuário com rapidez suficiente.The result is that the count can be incremented over three times by the user because the button isn't removed by the UI quickly enough. A maneira correta de atingir o limite de três count incrementos é mostrada no exemplo a seguir:The correct way to achieve the limit of three count increments is shown in the following example:

<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++;
        }
    }
}

Ao adicionar a if (count < 3) { ... } verificação dentro do manipulador, a decisão de incrementar count se baseia no estado atual do aplicativo.By adding the if (count < 3) { ... } check inside the handler, the decision to increment count is based on the current app state. A decisão não se baseia no estado da interface do usuário como estava no exemplo anterior, que pode estar temporariamente obsoleta.The decision isn't based on the state of the UI as it was in the previous example, which might be temporarily stale.

Proteção contra vários despachosGuard against multiple dispatches

Se um retorno de chamada de evento invocar uma operação de execução longa de forma assíncrona, como a busca de dados de um serviço externo ou banco de dado, considere o uso de uma proteção.If an event callback invokes a long running operation asynchronously, such as fetching data from an external service or database, consider using a guard. A proteção pode impedir que o usuário enfileirar várias operações enquanto a operação está em andamento com comentários visuais.The guard can prevent the user from queueing up multiple operations while the operation is in progress with visual feedback. O código de componente a seguir define isLoading para true enquanto GetForecastAsync obtém dados do servidor.The following component code sets isLoading to true while GetForecastAsync obtains data from the server. Embora isLoading seja true, o botão é desabilitado na interface do usuário:While isLoading is true, the button is disabled in the UI:

@page "/fetchdata"
@using BlazorServerSample.Data
@inject WeatherForecastService ForecastService

<button disabled="@isLoading" @onclick="UpdateForecasts">Update</button>

@code {
    private bool isLoading;
    private WeatherForecast[] forecasts;

    private async Task UpdateForecasts()
    {
        if (!isLoading)
        {
            isLoading = true;
            forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
            isLoading = false;
        }
    }
}

O padrão de proteção demonstrado no exemplo anterior funcionará se a operação em segundo plano for executada de forma assíncrona com o padrão de await de -de async.The guard pattern demonstrated in the preceding example works if the background operation is executed asynchronously with the async-await pattern.

Cancelar antes e evitar usar-After-DisposeCancel early and avoid use-after-dispose

Além de usar uma proteção, conforme descrito na seção proteção contra vários despachos , considere usar um CancellationToken para cancelar operações de execução longa quando o componente for descartado.In addition to using a guard as described in the Guard against multiple dispatches section, consider using a CancellationToken to cancel long-running operations when the component is disposed. Essa abordagem tem o benefício adicional de evitar o uso-After-Dispose nos componentes:This approach has the added benefit of avoiding use-after-dispose in components:

@implements IDisposable

...

@code {
    private readonly CancellationTokenSource TokenSource = 
        new CancellationTokenSource();

    private async Task UpdateForecasts()
    {
        ...

        forecasts = await ForecastService.GetForecastAsync(DateTime.Now, 
            TokenSource.Token);

        if (TokenSource.Token.IsCancellationRequested)
        {
           return;
        }

        ...
    }

    public void Dispose()
    {
        CancellationTokenSource.Cancel();
    }
}

Evitar eventos que produzem grandes quantidades de dadosAvoid events that produce large amounts of data

Alguns eventos DOM, como oninput ou onscroll, podem produzir uma grande quantidade de dados.Some DOM events, such as oninput or onscroll, can produce a large amount of data. Evite usar esses eventos em aplicativos do Blazor Server.Avoid using these events in Blazor server apps.

Diretrizes de segurança adicionaisAdditional security guidance

As diretrizes para proteger os aplicativos ASP.NET Core se aplicam a aplicativos Blazor Server e são abordadas nas seguintes seções:The guidance for securing ASP.NET Core apps apply to Blazor Server apps and are covered in the following sections:

Registro em log e dados confidenciaisLogging and sensitive data

As interações de interoperabilidade do JS entre o cliente e o servidor são registradas nos logs do servidor com instâncias de ILogger.JS interop interactions between the client and server are recorded in the server's logs with ILogger instances. Blazor evita informações confidenciais de log, como eventos reais ou entradas e saídas de interoperabilidade do JS. avoids logging sensitive information, such as actual events or JS interop inputs and outputs.

Quando ocorre um erro no servidor, a estrutura notifica o cliente e destrói a sessão.When an error occurs on the server, the framework notifies the client and tears down the session. Por padrão, o cliente recebe uma mensagem de erro genérica que pode ser vista nas ferramentas de desenvolvedor do navegador.By default, the client receives a generic error message that can be seen in the browser's developer tools.

O erro do lado do cliente não inclui a pilha de chamadas e não fornece detalhes sobre a causa do erro, mas os logs do servidor contêm essas informações.The client-side error doesn't include the callstack and doesn't provide detail on the cause of the error, but server logs do contain such information. Para fins de desenvolvimento, informações de erro confidenciais podem ser disponibilizadas para o cliente habilitando erros detalhados.For development purposes, sensitive error information can be made available to the client by enabling detailed errors.

Habilitar erros detalhados com:Enable detailed errors with:

  • CircuitOptions.DetailedErrors.CircuitOptions.DetailedErrors.
  • DetailedErrors chave de configuração.DetailedErrors configuration key. Por exemplo, defina a variável de ambiente ASPNETCORE_DETAILEDERRORS como um valor de true.For example, set the ASPNETCORE_DETAILEDERRORS environment variable to a value of true.

Aviso

Expor informações de erro aos clientes na Internet é um risco de segurança que sempre deve ser evitado.Exposing error information to clients on the Internet is a security risk that should always be avoided.

Proteger informações em trânsito com HTTPSProtect information in transit with HTTPS

o Blazor Server usa SignalR para comunicação entre o cliente e o servidor.Blazor Server uses SignalR for communication between the client and the server. o Blazor Server normalmente usa o transporte que SignalR negocia, que normalmente é WebSockets.Blazor Server normally uses the transport that SignalR negotiates, which is typically WebSockets.

o Blazor Server não garante a integridade e a confidencialidade dos dados enviados entre o servidor e o cliente.Blazor Server doesn't ensure the integrity and confidentiality of the data sent between the server and the client. Sempre use HTTPS.Always use HTTPS.

Scripts entre sites (XSS)Cross-site scripting (XSS)

O XSS (script entre sites) permite que uma parte não autorizada execute lógica arbitrária no contexto do navegador.Cross-site scripting (XSS) allows an unauthorized party to execute arbitrary logic in the context of the browser. Um aplicativo comprometido poderia potencialmente executar código arbitrário no cliente.A compromised app could potentially run arbitrary code on the client. A vulnerabilidade pode ser usada para potencialmente executar várias ações mal-intencionadas no servidor:The vulnerability could be used to potentially perform a number of malicious actions against the server:

  • Despache eventos falsos/inválidos para o servidor.Dispatch fake/invalid events to the server.
  • Falha de expedição/conclusões de renderização inválidas.Dispatch fail/invalid render completions.
  • Evite a expedição de conclusões de renderização.Avoid dispatching render completions.
  • Despache chamadas de interoperabilidade do JavaScript para o .NET.Dispatch interop calls from JavaScript to .NET.
  • Modifique a resposta das chamadas de interoperabilidade do .NET para o JavaScript.Modify the response of interop calls from .NET to JavaScript.
  • Evite distribuir resultados de interoperabilidade do .NET para JS.Avoid dispatching .NET to JS interop results.

A estrutura do Blazor Server executa as etapas para proteger contra algumas das ameaças anteriores:The Blazor Server framework takes steps to protect against some of the preceding threats:

  • Interromperá a produção de novas atualizações de interface do usuário se o cliente não estiver confirmando lotes de renderização.Stops producing new UI updates if the client isn't acknowledging render batches. Configurado com CircuitOptions.MaxBufferedUnacknowledgedRenderBatches.Configured with CircuitOptions.MaxBufferedUnacknowledgedRenderBatches.
  • O tempo limite de qualquer chamada .NET para JavaScript após um minuto sem receber uma resposta do cliente.Times out any .NET to JavaScript call after one minute without receiving a response from the client. Configurado com CircuitOptions.JSInteropDefaultCallTimeout.Configured with CircuitOptions.JSInteropDefaultCallTimeout.
  • Executa a validação básica em todas as entradas provenientes do navegador durante a interoperabilidade do JS:Performs basic validation on all input coming from the browser during JS interop:
    • As referências do .NET são válidas e do tipo esperado pelo método .NET..NET references are valid and of the type expected by the .NET method.
    • Os dados não estão malformados.The data isn't malformed.
    • O número correto de argumentos para o método está presente na carga.The correct number of arguments for the method are present in the payload.
    • Os argumentos ou o resultado podem ser desserializados corretamente antes de invocar o método.The arguments or result can be deserialized correctly before invoking the method.
  • Executa a validação básica em todas as entradas provenientes do navegador de eventos expedidos:Performs basic validation in all input coming from the browser from dispatched events:
    • O evento tem um tipo válido.The event has a valid type.
    • Os dados do evento podem ser desserializados.The data for the event can be deserialized.
    • Há um manipulador de eventos associado ao evento.There's an event handler associated with the event.

Além das proteções que a estrutura implementa, o aplicativo deve ser codificado pelo desenvolvedor para proteger contra ameaças e tomar as medidas apropriadas:In addition to the safeguards that the framework implements, the app must be coded by the developer to safeguard against threats and take appropriate actions:

  • Sempre validar dados ao manipular eventos.Always validate data when handling events.
  • Execute a ação apropriada ao receber dados inválidos:Take appropriate action upon receiving invalid data:
    • Ignorar os dados e retornar.Ignore the data and return. Isso permite que o aplicativo continue processando solicitações.This allows the app to continue processing requests.
    • Se o aplicativo determinar que a entrada é ilegítimo e não pôde ser produzida pelo cliente legítimo, acione uma exceção.If the app determines that the input is illegitimate and couldn't be produced by legitimate client, throw an exception. Lançar uma exceção destrói o circuito e encerra a sessão.Throwing an exception tears down the circuit and ends the session.
  • Não confie na mensagem de erro fornecida por conclusões de lote de renderização incluídas nos logs.Don't trust the error message provided by render batch completions included in the logs. O erro é fornecido pelo cliente e, em geral, não pode ser confiável, pois o cliente pode estar comprometido.The error is provided by the client and can't generally be trusted, as the client might be compromised.
  • Não confie na entrada em chamadas de interoperabilidade JS em qualquer direção entre os métodos JavaScript e .NET.Don't trust the input on JS interop calls in either direction between JavaScript and .NET methods.
  • O aplicativo é responsável por validar que o conteúdo dos argumentos e dos resultados é válido, mesmo que os argumentos ou os resultados sejam desserializados corretamente.The app is responsible for validating that the content of arguments and results are valid, even if the arguments or results are correctly deserialized.

Para que uma vulnerabilidade de XSS exista, o aplicativo deve incorporar a entrada do usuário na página renderizada.For a XSS vulnerability to exist, the app must incorporate user input in the rendered page. os componentes do Blazor Server executam uma etapa de tempo de compilação em que a marcação em um arquivo . Razor é transformada em lógica de procedimento C# .Blazor Server components execute a compile-time step where the markup in a .razor file is transformed into procedural C# logic. Em tempo de execução C# , a lógica cria uma árvore de renderização que descreve os elementos, o texto e os componentes filho.At runtime, the C# logic builds a render tree describing the elements, text, and child components. Isso é aplicado ao DOM do navegador por meio de uma sequência de instruções de JavaScript (ou é serializado para HTML no caso de pré-processamento):This is applied to the browser's DOM via a sequence of JavaScript instructions (or is serialized to HTML in the case of prerendering):

  • A entrada do usuário processada por meio de sintaxe Razor normal (por exemplo, @someStringValue) não expõe uma vulnerabilidade de XSS porque a sintaxe Razor é adicionada ao DOM por meio de comandos que só podem gravar texto.User input rendered via normal Razor syntax (for example, @someStringValue) doesn't expose a XSS vulnerability because the Razor syntax is added to the DOM via commands that can only write text. Mesmo se o valor incluir marcação HTML, o valor será exibido como texto estático.Even if the value includes HTML markup, the value is displayed as static text. Ao renderizar, a saída é codificada em HTML, que também exibe o conteúdo como texto estático.When prerendering, the output is HTML-encoded, which also displays the content as static text.
  • Marcas de script não são permitidas e não devem ser incluídas na árvore de renderização de componente do aplicativo.Script tags aren't allowed and shouldn't be included in the app's component render tree. Se uma marca de script for incluída na marcação de um componente, um erro de tempo de compilação será gerado.If a script tag is included in a component's markup, a compile-time error is generated.
  • Os autores de componentes podem criar C# componentes no sem usar o Razor.Component authors can author components in C# without using Razor. O autor do componente é responsável por usar as APIs corretas ao emitir a saída.The component author is responsible for using the correct APIs when emitting output. Por exemplo, use builder.AddContent(0, someUserSuppliedString) e não builder.AddMarkupContent(0, someUserSuppliedString), pois o último pode criar uma vulnerabilidade de XSS.For example, use builder.AddContent(0, someUserSuppliedString) and not builder.AddMarkupContent(0, someUserSuppliedString), as the latter could create a XSS vulnerability.

Como parte da proteção contra ataques XSS, considere a implementação de mitigações XSS, como a política de segurança de conteúdo (CSP).As part of protecting against XSS attacks, consider implementing XSS mitigations, such as Content Security Policy (CSP).

Para obter mais informações, consulte Evitar Cross-Site Scripting (XSS) no ASP.NET Core.For more information, see Evitar Cross-Site Scripting (XSS) no ASP.NET Core.

Proteção entre origensCross-origin protection

Os ataques entre origens envolvem um cliente de uma origem diferente executando uma ação no servidor.Cross-origin attacks involve a client from a different origin performing an action against the server. A ação mal-intencionada é normalmente uma solicitação GET ou uma POSTAgem de formulário (solicitação entre sites forjada, CSRF), mas também é possível abrir um WebSocket mal-intencionado.The malicious action is typically a GET request or a form POST (Cross-Site Request Forgery, CSRF), but opening a malicious WebSocket is also possible. os aplicativos do Blazor Server oferecem as mesmas garantias de que qualquer outro aplicativo SignalR usando a oferta do protocolo Hub:Blazor Server apps offer the same guarantees that any other SignalR app using the hub protocol offer:

  • os aplicativos do Blazor Server podem ser acessados entre origens, a menos que sejam tomadas medidas adicionais para impedi-lo.Blazor Server apps can be accessed cross-origin unless additional measures are taken to prevent it. Para desabilitar o acesso entre origens, desabilite o CORS no ponto de extremidade adicionando o middleware do CORS ao pipeline e adicionando o DisableCorsAttribute aos metadados do ponto de extremidade do Blazor ou limite o conjunto de origens permitidas configurando SignalR para compartilhamento de recursos entre origens.To disable cross-origin access, either disable CORS in the endpoint by adding the CORS middleware to the pipeline and adding the DisableCorsAttribute to the Blazor endpoint metadata or limit the set of allowed origins by configuring SignalR for cross-origin resource sharing.
  • Se o CORS estiver habilitado, etapas adicionais poderão ser necessárias para proteger o aplicativo dependendo da configuração do CORS.If CORS is enabled, extra steps might be required to protect the app depending on the CORS configuration. Se o CORS for habilitado globalmente, o CORS poderá ser desabilitado para o Hub de servidor Blazor adicionando os metadados de DisableCorsAttribute aos metadados do ponto de extremidade depois de chamar hub.MapBlazorHub().If CORS is globally enabled, CORS can be disabled for the Blazor Server hub by adding the DisableCorsAttribute metadata to the endpoint metadata after calling hub.MapBlazorHub().

Para obter mais informações, consulte Impedir ataques de solicitação intersite forjada (XSRF/CSRF) no ASP.NET Core.For more information, see Impedir ataques de solicitação intersite forjada (XSRF/CSRF) no ASP.NET Core.

Sensor de cliqueClick-jacking

A tomada de clique envolve a renderização de um site como um <iframe> dentro de um site de uma origem diferente para induzir o usuário a executar ações no site sob ataque.Click-jacking involves rendering a site as an <iframe> inside a site from a different origin in order to trick the user into performing actions on the site under attack.

Para proteger um aplicativo contra a renderização dentro de um <iframe>, use o CSP (política de segurança de conteúdo) e o cabeçalho de X-Frame-Options.To protect an app from rendering inside of an <iframe>, use Content Security Policy (CSP) and the X-Frame-Options header. Para obter mais informações, consulte MDN Web docs: X-Frame-Options.For more information, see MDN web docs: X-Frame-Options.

Redirecionamentos abertosOpen redirects

Quando uma sessão de aplicativo do Blazor Server é iniciada, o servidor executa a validação básica das URLs enviadas como parte do início da sessão.When a Blazor Server app session starts, the server performs basic validation of the URLs sent as part of starting the session. A estrutura verifica se a URL base é um pai da URL atual antes de estabelecer o circuito.The framework checks that the base URL is a parent of the current URL before establishing the circuit. Nenhuma verificação adicional é executada pela estrutura.No additional checks are performed by the framework.

Quando um usuário seleciona um link no cliente, a URL do link é enviada para o servidor, que determina a ação a ser tomada.When a user selects a link on the client, the URL for the link is sent to the server, which determines what action to take. Por exemplo, o aplicativo pode executar uma navegação no lado do cliente ou indicar ao navegador para ir para o novo local.For example, the app may perform a client-side navigation or indicate to the browser to go to the new location.

Os componentes também podem disparar solicitações de navegação programaticamente por meio do uso de NavigationManager.Components can also trigger navigation requests programatically through the use of NavigationManager. Nesses cenários, o aplicativo pode executar uma navegação no lado do cliente ou indicar ao navegador para ir para o novo local.In such scenarios, the app might perform a client-side navigation or indicate to the browser to go to the new location.

Os componentes devem:Components must:

  • Evite usar a entrada do usuário como parte dos argumentos de chamada de navegação.Avoid using user input as part of the navigation call arguments.
  • Valide os argumentos para garantir que o destino seja permitido pelo aplicativo.Validate arguments to ensure that the target is allowed by the app.

Caso contrário, um usuário mal-intencionado pode forçar o navegador a ir para um site controlado pelo invasor.Otherwise, a malicious user can force the browser to go to an attacker-controlled site. Nesse cenário, o invasor vaza o aplicativo para usar alguma entrada do usuário como parte da invocação do método NavigationManager.Navigate.In this scenario, the attacker tricks the app into using some user input as part of the invocation of the NavigationManager.Navigate method.

Esse aviso também se aplica ao renderizar links como parte do aplicativo:This advice also applies when rendering links as part of the app:

  • Se possível, use links relativos.If possible, use relative links.
  • Valide se os destinos de link absoluto são válidos antes de incluí-los em uma página.Validate that absolute link destinations are valid before including them in a page.

Para obter mais informações, consulte Impedir ataques de redirecionamento aberto no ASP.NET Core.For more information, see Impedir ataques de redirecionamento aberto no ASP.NET Core.

Autenticação e autorizaçãoAuthentication and authorization

Para obter orientação sobre autenticação e autorização, consulte Autenticação e autorização do ASP.NET Core Blazor.For guidance on authentication and authorization, see Autenticação e autorização do ASP.NET Core Blazor.

Lista de verificação de segurançaSecurity checklist

A seguinte lista de considerações de segurança não é abrangente:The following list of security considerations isn't comprehensive:

  • Validar argumentos de eventos.Validate arguments from events.
  • Validar entradas e resultados de chamadas de interoperabilidade JS.Validate inputs and results from JS interop calls.
  • Evite usar (ou validar com antecedência) a entrada do usuário para chamadas de interoperabilidade .NET para JS.Avoid using (or validate beforehand) user input for .NET to JS interop calls.
  • Impedir que o cliente aloque uma quantidade desassociada de memória.Prevent the client from allocating an unbound amount of memory.
    • Dados dentro do componente.Data within the component.
    • DotNetObject referências retornadas ao cliente.DotNetObject references returned to the client.
  • Proteção contra vários despachos.Guard against multiple dispatches.
  • Cancelar operações de execução longa quando o componente for descartado.Cancel long-running operations when the component is disposed.
  • Evite eventos que produzem grandes quantidades de dados.Avoid events that produce large amounts of data.
  • Evite usar a entrada do usuário como parte das chamadas para NavigationManager.Navigate e validar a entrada do usuário para URLs em um conjunto de origens permitidas primeiro se for inevitável.Avoid using user input as part of calls to NavigationManager.Navigate and validate user input for URLs against a set of allowed origins first if unavoidable.
  • Não tome decisões de autorização com base no estado da interface do usuário, mas somente no estado do componente.Don't make authorization decisions based on the state of the UI but only from component state.
  • Considere o uso da CSP (política de segurança de conteúdo) para proteger contra ataques de XSS.Consider using Content Security Policy (CSP) to protect against XSS attacks.
  • Considere usar o CSP e as opções X-frame para proteger contra o clique.Consider using CSP and X-Frame-Options to protect against click-jacking.
  • Verifique se as configurações de CORS são apropriadas ao habilitar o CORS ou desabilitar explicitamente o CORS para aplicativos Blazor.Ensure CORS settings are appropriate when enabling CORS or explicitly disable CORS for Blazor apps.
  • Teste para garantir que os limites do lado do servidor para o aplicativo Blazor forneçam uma experiência de usuário aceitável sem níveis inaceitáveis de risco.Test to ensure that the server-side limits for the Blazor app provide an acceptable user experience without unacceptable levels of risk.