Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Observação
Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 9 deste artigo.
Advertência
Esta versão do ASP.NET Core não é mais suportada. Para obter mais informações, consulte a Política de suporte do .NET e .NET Core. Para a versão atual, consulte a versão .NET 9 deste artigo.
Important
Estas informações referem-se a um produto de pré-lançamento que pode ser substancialmente modificado antes de ser lançado comercialmente. A Microsoft não oferece garantias, expressas ou implícitas, em relação às informações fornecidas aqui.
Para a versão atual, consulte a versão .NET 9 deste artigo.
This article explains how to mitigate security threats in interactive server-side Blazor.
As aplicações adotam um modelo de processamento de dados stateful , onde o servidor e o cliente mantêm um relacionamento de longa duração. O estado persistente é mantido por um circuito , que pode abranger conexões que também são potencialmente de longa duração.
Quando um usuário visita um site, o servidor cria um circuito na memória do servidor. 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. Para executar essas ações, um circuito invoca funções JavaScript no navegador do usuário e métodos .NET no servidor. This two-way JavaScript-based interaction is referred to as JavaScript interop (JS interop).
Uma vez que a interoperabilidade JS ocorre pela Internet e o cliente usa um navegador remoto, as aplicações web partilham a maioria das preocupações com a segurança. Este tópico descreve ameaças comuns a aplicativos Blazor do lado do servidor e fornece orientações de mitigação de ameaças focadas em aplicativos voltados para a Internet.
In constrained environments, such as inside corporate networks or intranets, some of the mitigation guidance either:
- Não se aplica no ambiente restrito.
- Não vale a pena o custo de implementação porque o risco de segurança é baixo em um ambiente restrito.
Componentes interativos do servidor com a compressão do WebSocket ativada
Compression can expose the app to side-channel attacks against the TLS encryption of the connection, such as CRIME and BREACH attacks. Estes tipos de ataques exigem que o ciberatacante:
- Forçar um navegador a emitir solicitações com uma carga que o ciberatacante controla para um site vulnerável através de publicação cruzada de formulários ou incorporando o site num iframe de outro site.
- Observe o comprimento da resposta compactada e criptografada pela rede.
For the app to be vulnerable, it must reflect the payload from the cyberattacker in the response, for example, by writing out the path or the query string into the response. Usando o comprimento da resposta, o ciberatacante pode "adivinhar" qualquer informação sobre a resposta, ignorando a criptografia da conexão.
De um modo geral, as aplicações Blazor podem permitir a compactação na ligação WebSocket com medidas de segurança apropriadas.
O aplicativo pode ficar vulnerável quando pega conteúdo da solicitação (por exemplo, o caminho ou a cadeia de caracteres de consulta) que pode ser influenciado por um invasor cibernético e o reproduz no HTML da página ou o torna parte da resposta.
Blazor aplica automaticamente as seguintes medidas de segurança:
Quando a compactação é configurada, Blazor bloqueia automaticamente a incorporação do aplicativo em um iframe, o que bloqueia a renderização da resposta inicial (descompactada) do servidor e impede que a conexão WebSocket seja iniciada.
A restrição de incorporar o aplicativo em um iframe pode ser relaxada. No entanto, relaxar a restrição expõe o aplicativo a ataques se o documento incorporado for comprometido por meio de uma vulnerabilidade de script entre sites, pois isso dá ao ciberatacante uma maneira de executar o ataque.
Normalmente, para que esse tipo de ataque ocorra, o aplicativo deve reproduzir repetidamente o conteúdo nas respostas para que o ciberatacante possa adivinhar a resposta. Dada a forma como Blazor renderiza (ele renderiza uma vez e, em seguida, produz diffs do conteúdo apenas para os elementos que mudaram), isso é difícil para um ciberatacante realizar. No entanto, não é impossível para um ciberatacante, por isso é preciso ter cuidado para evitar renderizar informações confidenciais ao lado de informações externas que podem ser manipuladas por um ciberatacante. Alguns exemplos disso são:
Renderizar Informações de Identificação Pessoal (PII) na página ao mesmo tempo em que renderiza dados de banco de dados que foram adicionados por outro usuário.
Rendering PII information on to the page at the same time as data coming from another user via JS interop or a local singleton service on the server.
Em geral, recomendamos que você evite renderizar componentes que contenham informações confidenciais ao lado de componentes que possam renderizar dados de fontes não confiáveis como parte do mesmo lote de renderização. As fontes não confiáveis incluem parâmetros de rota, cadeias de caracteres de consulta, dados de interoperabilidade JS e qualquer outra fonte de dados que um usuário de terceiros possa controlar (bancos de dados, serviços externos).
Estado compartilhado
Os aplicativos Blazor do lado do servidor vivem na memória do servidor e várias sessões de aplicativos são hospedadas no mesmo processo. For each app session, Blazor starts a circuit with its own dependency injection container scope, thus scoped services are unique per Blazor session.
Advertência
Não recomendamos que aplicações no mesmo servidor partilhem estado usando serviços de singleton, a menos que se tenha extremo cuidado, pois isto pode introduzir vulnerabilidades de segurança, como o vazamento do estado do utilizador entre circuitos.
You can use stateful singleton services in Blazor apps if they're specifically designed for it. Por exemplo, o uso de um cache de memória singleton é aceitável porque um cache de memória requer uma chave para acessar uma determinada entrada. Supondo que os usuários não tenham controle sobre as chaves de cache usadas com o cache, o estado armazenado no cache não vaza entre circuitos.
Para obter orientações gerais sobre a gestão do Estado, consulte ASP.NET Core Blazor State Management.
IHttpContextAccessor
/HttpContext
For more information, see IHttpContextAccessor/HttpContext in ASP.NET Core Blazor apps.
Esgotamento de recursos
O esgotamento de recursos pode ocorrer quando um cliente interage com o servidor e faz com que o servidor consuma recursos excessivos. O consumo excessivo de recursos afeta principalmente:
Os ataques de negação de serviço (DoS) geralmente procuram esgotar os recursos de um aplicativo ou servidor. No entanto, o esgotamento de recursos não é necessariamente o resultado de um ataque ao sistema. Por exemplo, recursos finitos podem ser esgotados devido à alta demanda do usuário. A DoS é abordada mais detalhadamente na seção DoS.
Recursos externos à estrutura Blazor, como bancos de dados e identificadores de arquivo (usados para ler e gravar arquivos), também podem enfrentar esgotamento de recursos. Para obter mais informações, consulte ASP.NET Core Best Practices.
CPU
O esgotamento da CPU pode ocorrer quando um ou mais clientes forçam o servidor a executar trabalho intensivo da CPU.
Por exemplo, considere um aplicativo que calcula um número de Fibonnacci . Um número de Fibonnacci é produzido a partir de uma sequência de Fibonnacci, onde cada número na sequência é a soma dos dois números anteriores. A quantidade de trabalho necessária para chegar à resposta depende do comprimento da sequência e do tamanho do valor inicial. Se o aplicativo não colocar limites na solicitação de um cliente, os cálculos intensivos de CPU podem dominar o tempo da CPU e diminuir o desempenho de outras tarefas. O consumo excessivo de recursos é uma preocupação de segurança que afeta a disponibilidade.
O esgotamento da CPU é uma preocupação para todos os aplicativos voltados para o público. Em aplicações Web normais, os pedidos e as ligações expiram como salvaguarda, mas as aplicações Blazor não fornecem as mesmas salvaguardas. Blazor aplicativos devem incluir verificações e limites apropriados antes de executar um trabalho potencialmente intensivo de CPU.
Memória
O esgotamento da memória pode ocorrer quando um ou mais clientes forçam o servidor a consumir uma grande quantidade de memória.
Por exemplo, considere um aplicativo com um componente que aceita e exibe uma lista de itens. Se o aplicativo Blazor não colocar limites no número de itens permitidos ou no número de itens renderizados de volta ao 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 seja prejudicado. O servidor pode falhar ou abrandar ao ponto de parecer ter falhado.
Considere o seguinte cenário para manter e exibir uma lista de itens que pertencem a um possível cenário de esgotamento de memória no servidor:
- Os itens em uma propriedade ou campo
List<T>
usam a memória do servidor. Se o aplicativo permitir que a lista de itens cresça sem limites, há um risco de o servidor ficar sem memória. A falta de memória faz com que a sessão atual termine (falhe) e todas as sessões simultâneas nessa instância do servidor recebem uma exceção de falta de memória. Para evitar que esse cenário ocorra, o aplicativo deve usar uma estrutura de dados que imponha um limite de itens para usuários simultâneos. - 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. Sem um limite no número de itens, as demandas de memória podem esgotar a memória disponível do servidor. Para evitar esse cenário, use uma das seguintes abordagens:
- Use listas paginadas ao renderizar.
- Exiba apenas os primeiros 100 a 1.000 itens e exija que o usuário insira critérios de pesquisa para encontrar itens além dos itens exibidos.
- For a more advanced rendering scenario, implement lists or grids that support virtualization. Usando a virtualização, as listas renderizam apenas um subconjunto de itens atualmente visíveis para o utilizador. Quando o usuário interage com a barra de rolagem na interface do usuário, o componente renderiza apenas os itens necessários para exibição. Os itens que atualmente não são necessários para exibição podem ser mantidos em armazenamento secundário, que é a abordagem ideal. Itens não exibidos também podem ser mantidos na memória, o que é menos ideal.
Observação
Blazor tem suporte interno para virtualização. Para obter mais informações, consulte ASP.NET Core Razor component virtualization.
Blazor 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. Por exemplo, um aplicativo Blazor WebAssembly é executado inteiramente no cliente e usa apenas recursos de memória do cliente. Para um aplicativo Blazor do lado do servidor, a memória consumida pelo aplicativo pertence ao servidor e é compartilhada entre clientes na instância do servidor.
Server-side memory demands are a consideration for all server-side Blazor apps. No entanto, a maioria das aplicações web é sem estado, e a memória usada durante o processamento de um pedido é liberada quando a resposta é enviada. Como recomendação geral, não permita que os clientes aloquem uma quantidade ilimitada de memória, tal como em qualquer outra aplicação do lado do servidor que mantenha conexões com clientes. A memória consumida por um aplicativo Blazor do lado do servidor persiste por mais tempo do que uma única solicitação.
Observação
During development, a profiler can be used or a trace captured to assess memory demands of clients. A profiler or trace won't capture the memory allocated to a specific client. 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 cliente
O esgotamento da 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.
Blazor clientes estabelecem uma única conexão por sessão e mantêm a conexão aberta enquanto a janela do navegador estiver aberta. Given the persistent nature of the connections and the stateful nature of server-side Blazor apps, connection exhaustion is a greater risk to availability of the app.
Não há limite para o número de conexões por usuário para um aplicativo. Se o aplicativo exigir um limite de conexão, siga uma ou mais das seguintes abordagens:
- Requer autenticação, o que naturalmente limita a capacidade de usuários não autorizados de se conectarem ao aplicativo. Para que esse cenário seja eficaz, os usuários devem ser impedidos de provisionar novos usuários sob demanda.
- Limite o número de conexões por usuário. A limitação de conexões pode ser realizada através das seguintes abordagens. Tenha 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).
- Nível de aplicação
- Endpoint routing extensibility.
- Exija autenticação para se conectar ao aplicativo e acompanhar as sessões ativas por usuário.
- Rejeitar novas sessões ao atingir um limite.
- 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, evitando que um cliente esgote as conexões com o servidor.
- Nível do servidor: use um proxy/gateway na frente do aplicativo.
- O Azure Application Gateway é um balanceador de carga para tráfego web (camada 7 do modelo OSI) que permite gerir o tráfego para as suas aplicações web. Para obter mais informações, consulte Visão geral do suporte a WebSocket no Application Gateway.
- Azure Front Door é um serviço de balanceamento de carga para distribuir suas cargas de trabalho em vários recursos de computação.
- Nível de aplicação
- Requer autenticação, o que naturalmente limita a capacidade de usuários não autorizados de se conectarem ao aplicativo. Para que esse cenário seja eficaz, os usuários devem ser impedidos de provisionar novos usuários sob demanda.
- Limite o número de conexões por usuário. A limitação de conexões pode ser realizada através das seguintes abordagens. Tenha 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).
- Nível de aplicação
- Endpoint routing extensibility.
- Exija autenticação para se conectar ao aplicativo e acompanhar as sessões ativas por usuário.
- Rejeitar novas sessões ao atingir um limite.
- 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, evitando que um cliente esgote as conexões com o servidor.
- Nível do servidor
- Use um proxy/gateway na frente do aplicativo.
- Embora Long Polling seja suportado para aplicativos Blazor, WebSockets é o protocolo de transporte recomendado. Recomendamos selecionar um proxy/gateway que suporte WebSockets.
- Nível de aplicação
Ataques de negação de serviço (DoS)
ataques de negação de serviço (DoS) envolvem um cliente fazendo com que o servidor esgote um ou mais dos seus recursos, tornando a aplicação indisponível. Blazor apps include default limits and rely on other ASP.NET Core and SignalR limits that are set on CircuitOptions to protect against DoS attacks:
- CircuitOptions.DisconnectedCircuitMaxRetained
- CircuitOptions.DisconnectedCircuitRetentionPeriod
- CircuitOptions.JSInteropDefaultCallTimeout
- CircuitOptions.MaxBufferedUnacknowledgedRenderBatches
- HubConnectionContextOptions.MaximumReceiveMessageSize
Para obter mais informações e exemplos de codificação de configuração, consulte os seguintes artigos:
Interações com o navegador (cliente)
A client interacts with the server through JS interop event dispatching and render completion. JS interop communication goes both ways between JavaScript and .NET:
- Os eventos do navegador são enviados do cliente para o servidor de forma assíncrona.
- O servidor responde de forma assíncrona reprocessando a interface do usuário conforme necessário.
Funções JavaScript invocadas a partir do .NET
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.
- Há um tempo limite padrão para as chamadas (CircuitOptions.JSInteropDefaultCallTimeout) de um minuto. To configure this limit, see Call JavaScript functions from .NET methods in ASP.NET Core Blazor.
- Um token de cancelamento pode ser fornecido para controlar o cancelamento por chamada. Confie no tempo limite de chamada padrão sempre que possível e limite de tempo de qualquer chamada para o cliente se um token de cancelamento for fornecido.
- O resultado de uma chamada JavaScript não é confiável. O Blazor cliente de aplicativo em execução no navegador procura a função JavaScript a ser invocada. A função é invocada e o resultado ou um erro é produzido. Um cliente mal-intencionado pode tentar:
- Cause um problema no aplicativo retornando um erro da função JavaScript.
- Induza um comportamento não intencional no servidor retornando um resultado inesperado da função JavaScript.
Tome as seguintes precauções para se proteger contra os cenários anteriores:
- Wrap JS interop calls within
try-catch
statements to account for errors that might occur during the invocations. For more information, see Handle errors in ASP.NET Core Blazor apps. - Valide os dados retornados de invocações de interoperabilidade JS, incluindo mensagens de erro, antes de executar qualquer ação.
Métodos .NET invocados a partir do navegador
Não confie em chamadas de JavaScript para métodos .NET. Quando um método .NET é exposto ao JavaScript, considere como o método .NET é invocado:
- Trate qualquer método .NET exposto ao JavaScript como se fosse um ponto de extremidade público para o aplicativo.
- Valide a entrada.
- Certifique-se de que os valores estão dentro dos intervalos esperados.
- Verifique se o usuário tem permissão para executar a ação solicitada.
- Não aloque uma quantidade excessiva de recursos como parte da chamada do método .NET. Por exemplo, execute verificações e coloque limites no uso da CPU e da memória.
- Tenha em conta que os métodos estáticos e de instância podem ser expostos a clientes JavaScript. Evite compartilhar o estado entre sessões, a menos que o design exija o estado de compartilhamento com restrições apropriadas.
- Por exemplo, para métodos expostos por meio de objetos DotNetObjectReference que são originalmente criados por meio de injeção de dependência (DI), os objetos devem ser registrados como objetos de escopo delimitado. Isso se aplica a qualquer serviço de DI que o aplicativo usa.
- Para métodos estáticos, evite estabelecer um estado que não possa ser limitado ao cliente, a menos que o aplicativo, por conceção, esteja explicitamente a partilhar o estado entre todos os utilizadores de uma instância do servidor.
- Evite passar dados fornecidos pelo usuário em parâmetros para chamadas JavaScript. Se a passagem de dados em parâmetros for absolutamente necessária, certifique-se de que o código JavaScript lida com a passagem dos dados sem introduzir vulnerabilidades de Cross-site scripting (XSS). Por exemplo, não escreva dados fornecidos pelo usuário no DOM definindo a propriedade
innerHTML
de um elemento. Consider using Content Security Policy (CSP) to disableeval
and other unsafe JavaScript primitives. Para obter mais informações, consulte Impor uma política de segurança de conteúdo para ASP.NET Core Blazor e Guia CSP do MDN.
- Valide a entrada.
- Avoid implementing custom dispatching of .NET invocations on top of the framework's dispatching implementation. Expor métodos .NET para o navegador é um cenário avançado, não recomendado para desenvolvimento Blazor geral.
Eventos
Os eventos fornecem um ponto de entrada para um aplicativo. The same rules for safeguarding endpoints in web apps apply to event handling in Blazor apps. Um cliente mal-intencionado pode enviar quaisquer dados que deseje enviar como carga útil para um evento.
Por exemplo:
- 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. - Um
<input>
pode enviar quaisquer dados de texto para o servidor, ignorando a validação do lado do cliente.
O aplicativo deve validar os dados para qualquer evento que o aplicativo manipula. The Blazor framework forms components perform basic validations. Se o aplicativo usa componentes de formulários personalizados, o código personalizado deve ser escrito para validar os dados do evento, conforme apropriado.
Os eventos são assíncronos, portanto, vários eventos podem ser enviados para o servidor antes que o aplicativo tenha tempo para reagir produzindo uma nova renderização. Isto tem algumas implicações de segurança a considerar. A limitação de ações do cliente na aplicação deve ser executada dentro de manipuladores de eventos e não depender do estado atual da vista renderizada.
Considere um componente de contador que deve permitir que um usuário incremente um contador no máximo três vezes. O botão para incrementar o contador é condicionalmente baseado no valor de 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 despachar um ou mais eventos de incremento antes que a estrutura produza uma nova renderização desse componente. O resultado é que o count
pode ser incrementado mais de três vezes pelo usuário porque o botão não é removido pela interface do usuário com rapidez suficiente. A maneira correta de atingir o limite de três incrementos de count
é mostrada no exemplo a seguir:
<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++;
}
}
}
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 no exemplo anterior, que pode estar temporariamente obsoleto.
Protect against multiple dispatches
Se um callback de evento invocar uma operação demorada de forma assíncrona, como obter dados de um serviço externo ou banco de dados, considere usar uma salvaguarda. The safeguard can prevent the user from enqueueing multiple operations while the operation is in progress with visual feedback. O código de componente a seguir define isLoading
para true
enquanto DataService.GetDataAsync
obtém dados do servidor. While isLoading
is true
, the button is disabled in the UI:
<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;
}
}
}
O padrão de salvaguarda demonstrado no exemplo anterior funciona se a operação em segundo plano for executada de forma assíncrona com o padrão async
-await
.
Cancele com antecedência e evite o uso após o descarte do objeto
In addition to using a safeguard as described in the Protect against multiple dispatches section, consider using a CancellationToken to cancel long-running operations when the component is disposed. 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 UpdateData()
{
...
data = await DataService.GetDataAsync(DateTime.Now, TokenSource.Token);
if (TokenSource.Token.IsCancellationRequested)
{
return;
}
...
}
public void Dispose()
{
TokenSource.Cancel();
}
}
Evite eventos que produzem grandes quantidades de dados
Alguns eventos DOM, como oninput
ou onscroll
, podem produzir uma grande quantidade de dados. Avoid using these events in server-side Blazor server.
Orientações de segurança adicionais
As diretrizes para proteger aplicativos ASP.NET Core aplicam-se a aplicativos Blazor do lado do servidor e são abordadas nas seguintes seções deste artigo:
- Registo e dados sensíveis
- Proteja as informações em trânsito com HTTPS
- Cross-site scripting (XSS)
- Cross-origin protection
- Click-jacking
- Abrir redirecionamentos
Registo e dados confidenciais
JS interop interactions between the client and server are recorded in the server's logs with ILogger instances. Blazor 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. O cliente recebe uma mensagem de erro genérica que pode ser vista nas ferramentas de desenvolvedor do navegador.
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. For development purposes, sensitive error information can be made available to the client by enabling detailed errors.
Advertência
Expor informações de erro a clientes na Internet é um risco de segurança que deve ser sempre evitado.
Proteja as informações em trânsito com HTTPS
Blazor usa SignalR para comunicação entre o cliente e o servidor. Blazor normalmente usa o transporte que SignalR negocia, que normalmente é WebSockets.
Blazor não garante a integridade e confidencialidade dos dados enviados entre o servidor e o cliente. Use sempre HTTPS.
Cross-site scripting (XSS)
O script entre sites (XSS) permite que uma parte não autorizada execute lógica arbitrária no contexto do navegador. Um aplicativo comprometido pode potencialmente executar código arbitrário no cliente. A vulnerabilidade pode ser usada para executar várias ações maliciosas contra o servidor:
- Envie eventos falsos/inválidos para o servidor.
- Falha de envio/conclusões de renderização inválidas.
- Evite despachar finalizações de renderização.
- Envie chamadas de interoperabilidade do JavaScript para o .NET.
- Modify the response of interop calls from .NET to JavaScript.
- Avoid dispatching .NET to JS interop results.
A estrutura Blazor toma medidas para proteger contra algumas das ameaças anteriores:
- Stops producing new UI updates if the client isn't acknowledging render batches. Configured with CircuitOptions.MaxBufferedUnacknowledgedRenderBatches.
- Expira qualquer chamada .NET para JavaScript após um minuto sem receber uma resposta do cliente. Configured with CircuitOptions.JSInteropDefaultCallTimeout.
- Performs basic validation on all input coming from the browser during JS interop:
- As referências .NET são válidas e do tipo esperado pelo método .NET.
- Os dados não estão malformados.
- O número correto de argumentos para o método está presente na carga útil.
- Os argumentos ou resultados podem ser desserializados corretamente antes de invocar o método.
- Performs basic validation in all input coming from the browser from dispatched events:
- The event has a valid type.
- Os dados para o evento podem ser desserializados.
- Há um manipulador de eventos associado ao evento.
Além das salvaguardas que a estrutura implementa, o aplicativo deve ser codificado pelo desenvolvedor para se proteger contra ameaças e tomar as ações apropriadas:
- Sempre valide os dados ao manipular eventos.
- Tome as medidas apropriadas ao receber dados inválidos:
- Ignore os dados e retorne. Isso permite que o aplicativo continue processando solicitações.
- If the app determines that the input is illegitimate and couldn't be produced by legitimate client, throw an exception. Throwing an exception tears down the circuit and ends the session.
- Don't trust the error message provided by render batch completions included in the logs. O erro é fornecido pelo cliente e geralmente não é confiável, pois o cliente pode estar comprometido.
- Don't trust the input on JS interop calls in either direction between JavaScript and .NET methods.
- O aplicativo é responsável por validar se o conteúdo dos argumentos e resultados são válidos, mesmo que os argumentos ou resultados sejam desserializados corretamente.
Para que exista uma vulnerabilidade XSS, o aplicativo deve incorporar a entrada do usuário na página renderizada.
Blazor executes a compile-time step where the markup in a .razor
file is transformed into procedural C# logic. 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 JavaScript (ou é serializado para HTML no caso de pré-renderização):
- A entrada do usuário renderizada por meio da sintaxe Razor normal (por exemplo,
@someStringValue
) não expõe uma vulnerabilidade XSS porque a sintaxe Razor é adicionada ao DOM por meio de comandos que só podem escrever texto. Mesmo que o valor inclua marcação HTML, o valor é exibido como texto estático. Durante a pré-renderização, a saída é codificada em HTML, que também exibe o conteúdo como texto estático. - Os autores de componentes podem criar componentes em C# sem usar Razor. O autor do componente é responsável por usar as APIs corretas ao emitir a saída. Por exemplo, use
builder.AddContent(0, someUserSuppliedString)
e nãobuilder.AddMarkupContent(0, someUserSuppliedString)
, pois este último pode criar uma vulnerabilidade XSS.
- A entrada do usuário renderizada por meio da sintaxe Razor normal (por exemplo,
@someStringValue
) não expõe uma vulnerabilidade XSS porque a sintaxe Razor é adicionada ao DOM por meio de comandos que só podem escrever texto. Mesmo que o valor inclua marcação HTML, o valor é exibido como texto estático. Durante a pré-renderização, a saída é codificada em HTML, que também exibe o conteúdo como texto estático. - As tags de script não são permitidas e não devem ser incluídas na árvore de renderização de componentes do aplicativo. Se uma marca de script for incluída na marcação de um componente, um erro em tempo de compilação será gerado.
- Os autores de componentes podem criar componentes em C# sem usar Razor. O autor do componente é responsável por usar as APIs corretas ao emitir a saída. Por exemplo, use
builder.AddContent(0, someUserSuppliedString)
e nãobuilder.AddMarkupContent(0, someUserSuppliedString)
, pois este último pode criar uma vulnerabilidade XSS.
Considere mitigar ainda mais as vulnerabilidades do XSS. Por exemplo, implemente uma restritiva CSP (Política de Segurança de Conteúdo). Para obter mais informações, consulte Impor uma política de segurança de conteúdo para ASP.NET Core Blazor e Guia CSP do MDN.
For more information, see Prevent Cross-Site Scripting (XSS) in ASP.NET Core.
Cross-origin protection
Os ataques de origem cruzada envolvem um cliente de uma origem diferente executando uma ação contra o servidor. A ação maliciosa normalmente é uma solicitação GET ou um formulário POST (Cross-Site Request Forgery, CSRF), mas abrir um WebSocket mal-intencionado também é possível. Blazor apps offer the same guarantees that any other SignalR app using the hub protocol offer:
- Os aplicativos podem ser acessados entre origens, a menos que medidas adicionais sejam tomadas para evitá-lo. Para desabilitar o acesso entre origens, desabilite o CORS no ponto de extremidade adicionando o Middleware CORS ao pipeline e adicionando o DisableCorsAttribute aos metadados do ponto de extremidade Blazor ou limite o conjunto de origens permitidas configurando SignalR para o Cross-Origin Resource Sharing. Para obter orientação sobre restrições de origem de WebSocket, consulte suporte a WebSockets no ASP.NET Core.
- Se o CORS estiver habilitado, etapas adicionais podem ser necessárias para proteger o aplicativo, dependendo da configuração do CORS. Se o CORS estiver habilitado globalmente, o CORS poderá ser desabilitado para o hub de BlazorSignalR adicionando os metadados DisableCorsAttribute aos metadados do ponto de extremidade depois de chamar MapBlazorHub no construtor de rotas do ponto de extremidade.
Para obter mais informações, consulte Prevenção de ataques de falsificação de solicitações entre sites (XSRF/CSRF) no ASP.NET Core.
Click-jacking
O clickjacking envolve renderizar um site como um <iframe>
dentro de um site de uma origem diferente, a fim de enganar o utilizador para realizar ações no site que está sob ataque.
To protect an app from rendering inside of an <iframe>
, use Content Security Policy (CSP) and the X-Frame-Options
header. For CSP syntax, see MDN's CSP guide.
Para obter mais informações, consulte os seguintes recursos:
Abrir redirecionamentos
Quando uma sessão de aplicativo é iniciada, o servidor executa a validação básica das URLs enviadas como parte do início da sessão. A estrutura verifica se a URL base é um pai da URL atual antes de estabelecer o circuito. Nenhuma verificação adicional é realizada pela estrutura.
Quando um usuário seleciona um link no cliente, a URL do link é enviada para o servidor, que determina qual ação executar. Por exemplo, o aplicativo pode executar uma navegação no lado do cliente ou indicar ao navegador para ir para o novo local.
Os componentes também podem disparar solicitações de navegação programaticamente através do uso de 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.
Os componentes devem:
- Evite usar a entrada do usuário como parte dos argumentos da chamada de navegação.
- Valide argumentos para garantir que o alvo seja permitido pela aplicação.
Caso contrário, um usuário mal-intencionado pode forçar o navegador a ir para um site controlado por ciberatacantes. Nesse cenário, o ciberatacante engana o aplicativo para usar alguma entrada do usuário como parte da invocação do método NavigationManager.NavigateTo.
Este conselho também se aplica ao renderizar links como parte do aplicativo:
- Se possível, use links relativos.
- Valide se os destinos absolutos do link são válidos antes de incluí-los em uma página.
Para obter mais informações, consulte Impedir ataques de redirecionamento aberto no ASP.NET Core.
Lista de verificação de segurança
A lista de considerações de segurança a seguir não é abrangente:
- Validate arguments from events.
- Validate inputs and results from JS interop calls.
- Avoid using (or validate beforehand) user input for .NET to JS interop calls.
- Impedir que o cliente aloque uma quantidade ilimitada de memória.
- Data within the component.
- DotNetObjectReference objects returned to the client.
- Protect against multiple dispatches.
- Cancel long-running operations when the component is disposed.
- Evite eventos que produzam grandes quantidades de dados.
- Avoid using user input as part of calls to NavigationManager.NavigateTo 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 apenas a partir do estado do componente.
- Considere usar a Política de Segurança de Conteúdo (CSP) para proteger contra ataques XSS. Para obter mais informações, consulte Impor uma política de segurança de conteúdo para ASP.NET Core Blazor e Guia CSP do MDN.
- Considere usar CSP e X-Frame-Options para proteger contra clickjacking.
- Verifique se as configurações do CORS são apropriadas ao habilitar o CORS ou desabilitar explicitamente o CORS para aplicativos Blazor.
- 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.