Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Por Fiyaz Hasan e Rick Anderson
A falsificação de solicitação entre sites é um ataque contra aplicativos hospedados na Web em que um aplicativo Web mal-intencionado pode influenciar a interação entre um navegador cliente e um aplicativo Web que confia nesse navegador. Os ataques são possíveis porque os navegadores enviam automaticamente alguns tipos de tokens de autenticação com cada solicitação a um site. Essa forma de exploração também é conhecida como ataque de um clique ou sequestro de sessão, pois o ataque aproveita a sessão autenticada anteriormente pelo usuário. A falsificação de solicitação entre sites também é conhecida como XSRF ou CSRF.
Um exemplo de ataque CSRF:
Um usuário faz login no
www.good-banking-site.example.comusando a autenticação de formulários. O servidor autentica o usuário e emite uma resposta que inclui uma autenticação cookie. O site é vulnerável a ataques porque confia em qualquer solicitação recebida com uma autenticação cookieválida.O usuário visita um site mal-intencionado,
www.bad-crook-site.example.com.O site mal-intencionado,
www.bad-crook-site.example.com, contém um formulário HTML semelhante ao seguinte exemplo:<h1>Congratulations! You're a Winner!</h1> <form action="https://www.good-banking-site.example.com/api/account" method="post"> <input type="hidden" name="Transaction" value="withdraw" /> <input type="hidden" name="Amount" value="1000000" /> <input type="submit" value="Click to collect your prize!" /> </form>Observe que o formulário publica
actionno site vulnerável, não no site mal-intencionado. Essa é a parte "entre sites" do CSRF.O usuário seleciona o botão Enviar. O navegador faz a solicitação e inclui automaticamente a autenticação cookie para o domínio solicitado,
www.good-banking-site.example.com.A solicitação é executada no servidor
www.good-banking-site.example.comcom o contexto de autenticação do usuário e pode executar qualquer ação que um usuário autenticado tenha permissão para executar.
Além do cenário em que o usuário seleciona o botão para enviar o formulário, o site mal-intencionado pode:
- Executar um script que envia automaticamente o formulário.
- Enviar o envio do formulário como uma solicitação AJAX.
- Ocultar o formulário usando CSS.
Esses cenários alternativos não exigem nenhuma ação ou entrada do usuário além de visitar inicialmente o site mal-intencionado.
O uso de HTTPS não impede um ataque CSRF. O site malicioso pode enviar uma solicitação https://www.good-banking-site.example.com/ tão facilmente quanto uma solicitação insegura.
Alguns ataques visam pontos de extremidade que respondem a solicitações GET, nesse caso, uma marca de imagem pode ser usada para executar a ação. Essa forma de ataque é comum em sites de fórum que permitem imagens, mas bloqueiam JavaScript. Aplicativos que alteram o estado em solicitações GET, em que variáveis ou recursos são alterados, são vulneráveis a ataques mal-intencionados. Solicitações GET que alteram o estado são inseguras. Uma prática recomendada é nunca alterar o estado em uma solicitação GET.
Ataques CSRF são possíveis contra aplicativos Web que usam cookies para autenticação porque:
- Os navegadores armazenam cookies emitidos por um aplicativo Web.
- Os cookies armazenados incluem cookies de sessões de usuários autenticados.
- Os navegadores enviam todos os os cookies associados a um domínio para o aplicativo Web a cada solicitação, independentemente de como a solicitação para o aplicativo foi gerada no navegador.
Entretanto, os ataques CSRF não se limitam à exploração de cookies. Por exemplo, a autenticação Básica e Digest também são vulneráveis. Depois que um usuário entra com a autenticação Básica ou Digest, o navegador envia automaticamente as credenciais até que a sessão termine.
Nesse contexto, a sessão refere-se à sessão do lado do cliente durante a qual o usuário é autenticado. Não está relacionado às sessões no lado do servidor nem ao middleware de sessão do ASP.NET Core.
Os usuários podem se proteger contra vulnerabilidades CSRF ao tomar precauções:
- Saia dos aplicativos Web quando terminar de usá-los.
- Limpe os os cookies do navegador periodicamente.
No entanto, as vulnerabilidades CSRF são fundamentalmente um problema com o aplicativo Web, não com o usuário final.
Conceitos básicos sobre autenticação
A autenticação baseada em Cookie é uma forma popular de autenticação. Os sistemas de autenticação baseados em token estão crescendo em popularidade, especialmente para Aplicativos de Página Única (SPAs).
Autenticação baseada em Cookie
Quando um usuário se autentica usando seu nome de usuário e senha, é emitido um token contendo um tíquete de autenticação. O token pode ser usado para autenticação e autorização. O token é armazenado como um cookie que é enviado com cada solicitação que o cliente faz. A geração e a validação deste cookie são realizadas por meio do cookie middleware de autenticação. O middleware serializa uma entidade de segurança de usuário em um criptografado cookie. Em solicitações subsequentes, o middleware valida o cookie, recria a entidade de segurança e atribui a entidade de segurança à propriedade HttpContext.User.
Autenticação baseada em token
Quando um usuário é autenticado, um token é emitido para ele (não um token antifalsificação). O token contém informações do usuário na forma de declarações ou um token de referência que aponta o aplicativo para o estado do usuário mantido no aplicativo. Quando um usuário tenta acessar um recurso que requer autenticação, o token é enviado para o aplicativo com um cabeçalho de autorização extra na forma de um token de portador. Essa abordagem torna o aplicativo sem estado. Em cada solicitação subsequente, o token é passado na solicitação de validação do lado do servidor. Esse token não é criptografado, ele é codificado. No servidor, o token é decodificado para acessar suas informações. Para enviar o token em solicitações subsequentes, armazene o token no armazenamento local do navegador. Colocar um token no armazenamento local do navegador e recuperá-lo e usá-lo como um token de portador fornece proteção contra ataques CSRF. No entanto, se o aplicativo estiver vulnerável à injeção de script por meio do XSS ou de um arquivo JavaScript externo comprometido, um ciberinvasor poderá recuperar qualquer valor do armazenamento local e enviá-lo para si mesmo. O ASP.NET Core codifica todas as saídas do lado do servidor de variáveis por padrão, reduzindo o risco de XSS. Se você substituir esse comportamento usando Html.Raw ou código personalizado com entrada não confiável, poderá aumentar o risco de XSS.
Não se preocupe com a vulnerabilidade CSRF se o token estiver armazenado no armazenamento local do navegador. O CSRF é uma preocupação quando o token é armazenado em um cookie. Para mais informações, consulte o problema do GitHub exemplo de código SPA adiciona dois cookies.
Vários aplicativos hospedados em um domínio
Ambientes de hospedagem compartilhados são vulneráveis ao sequestro de sessão, CSRF de entrada e outros ataques.
Embora example1.contoso.net e example2.contoso.net sejam hosts diferentes, há uma relação de confiança implícita entre hosts no domínio *.contoso.net. Essa relação de confiança implícita permite que hosts potencialmente não confiáveis afetem os cookies uns dos outros (as políticas de mesma origem que regem as solicitações AJAX não se aplicam necessariamente a cookies de HTTP).
Ataques que exploram cookies confiáveis entre aplicativos hospedados no mesmo domínio podem ser evitados ao não compartilhar domínios. Quando cada aplicativo é hospedado em seu próprio domínio, não há nenhuma relação de confiança implícita cookie a ser explorada.
Buscar cabeçalhos de metadados
Os navegadores modernos incluem cabeçalhos de solicitação Fetch Metadata — principalmente Sec-Fetch-Site — em cada solicitação.
Sec-Fetch-Site descreve a relação entre a origem que iniciou a solicitação e a origem que está sendo solicitada: same-origin identifica uma solicitação feita pelo site a si mesmo e same-sitecross-site identifica as solicitações iniciadas por outra origem. O cabeçalho Origin contém a origem iniciadora e serve como alternativa para navegadores anteriores ao Fetch Metadata.
Sec-Fetch-Site e Origin são cabeçalhos de solicitação proibidos: o navegador os define e o JavaScript em execução em uma página não pode substituí-los ou forja-los. Isso os torna um sinal confiável para diferenciar as próprias solicitações de um site das solicitações entre sites, sem precisar de um token emitido pelo servidor. A proteção CSRF automática integrada a ASP.NET Core usa esse sinal para rejeitar postagens de formulário entre sites que não são explicitamente confiáveis.
Proteção CSRF automática no ASP.NET Core
O ASP.NET Core inclui um middleware automático de proteção contra CSRF que vem habilitado por padrão em aplicações criadas com WebApplication.CreateBuilder. Ao contrário do sistema antiforgery baseado em token, esse middleware não emite ou valida tokens. Em vez disso, ele inspeciona os Sec-Fetch-SiteOrigin e Fetch e registra um veredicto de validação na solicitação. Os componentes que processam dados de formulário enviados impõem esse veredicto, rejeitando postagens de formulário entre origens que não são explicitamente confiáveis.
Para a maioria dos aplicativos, nenhuma alteração de código é necessária: solicitações de navegador de mesma origem, métodos HTTP seguros e clientes não navegadores (curl, servidor para servidor, aplicativos móveis) todos passam por não afetados. O middleware afeta principalmente aplicativos que aceitam postagens de formulário entre origens de um navegador, como um site que posta um formulário em uma API em uma origem diferente. Esses cenários precisam configurar o CORS para declarar a origem confiável ou excluir o endpoint.
Esse middleware é adicional ao sistema antifalsificação baseado em tokens. As duas proteções podem coexistir e ambas podem estar ativas no mesmo endpoint. Para comparar quando cada um se aplica, consulte Interação com antifalsificação baseada em token.
Como funciona
Para cada solicitação, o middleware avalia uma cadeia curta de regras para chegar a um veredicto — permitido ou negado. As verificações são executadas em ordem e a primeira correspondência vence:
-
Métodos HTTP seguros são sempre permitidos.
GET,HEAD,OPTIONSeTRACEsolicitações são encaminhadas. Isso segue a RFC 9110 §9.2.1 e está de acordo com a regra há muito estabelecida de que os endpoints não devem alterar seu estado emGET. -
Sec-Fetch-Site: same-originouSec-Fetch-Site: noneé permitido. Os navegadores modernos enviamSec-Fetch-Siteem todas as solicitações.same-originabrange a navegação e a busca normais no aplicativo enoneaborda as solicitações iniciadas diretamente pelo usuário (digitando uma URL, usando um indicador). Esse é o caminho de código mais comum— o tráfego do navegador mais legítimo sai daqui. - Uma origem confiável do CORS é permitida. Se a solicitação incluir o cabeçalho
Origine a política de CORS resolvida do endpoint considerar essa origem confiável, a solicitação será permitida. O middleware resolve a política da mesma forma que o middleware de CORS: primeiro, a política por ponto de extremidade de[EnableCors("name")]; depois, a política padrão registrada comAddDefaultPolicy. Consulte Permitir clientes de origem cruzada para obter limites importantes nessa regra. - Qualquer outro
Sec-Fetch-Sitevalor é negado. QuandoSec-Fetch-Siteécross-siteousame-sitee a origem não é confiável via CORS, a solicitação é negada. -
Não
Sec-Fetch-Site, masOriginestá presente: o middleware compara oOrigincom oscheme://host[:port]gerado a partir da solicitação. Se corresponderem, a solicitação é permitida; caso contrário, é negada. Este é o caminho alternativo para navegadores anteriores à especificação Fetch Metadata (lançada por volta de 2020). - Não
Sec-Fetch-Sitee nãoOrigin: a solicitação é permitida. Os navegadores sempre enviam pelo menos um destes em uma solicitação de gravação; portanto, uma solicitação sem ambos é quase certamente de um cliente não navegador, comocurl, o Postman, um aplicativo móvel ou um cliente servidor a servidor. O CSRF é um vetor de ataque restrito ao navegador, portanto essas solicitações passam sem serem bloqueadas.
O middleware registra esse veredicto na solicitação em vez de encerrar a solicitação em si. Para saber como e quando um veredicto negado se transforma em uma resposta HTTP 400 Bad Request , consulte validação adiada.
Validação adiada
O middleware não rejeita uma solicitação por conta própria. Em vez disso, ele registra sua decisão no atributo da IAntiforgeryValidationFeaturesolicitação — o mesmo atributo usado pelo sistema anti-falsificação baseado em token — no qual uma decisão de negação é registrada como inválido. A solicitação continua avançando pelo fluxo. Um veredicto inválido se torna um HTTP 400 Bad Request somente quando um componente que processa dados de formulário o observa. Esse adiamento corresponde à forma como o sistema baseado em tokens já funciona: a decisão é produzida antecipadamente, mas só é aplicada quando um formulário é enviado.
Os seguintes componentes leem IAntiforgeryValidationFeature e rejeitam uma solicitação com 400 - Bad Request quando o veredicto registrado é inválido:
- Ações de MVC protegidas por antiforgeria.
- Pontos de extremidade mínimos de API que associam um parâmetro de formulário.
- Blazor Pontos de extremidade SSR.
- Qualquer código que leia diretamente o formulário de solicitação, atuando como uma salvaguarda.
Cada consumidor primeiro confirma que um middleware antiforgery ou CSRF realmente foi executado antes de confiar no veredicto, de modo que um pipeline sem qualquer middleware não produz falsas rejeições.
Uma consequência desse modelo é que um endpoint que nunca lê dados de formulário é executado mesmo quando o resultado é inválido. Por exemplo, um endpoint de API JSON que vincula o corpo da solicitação a partir de JSON, ou um manipulador que ignora o corpo da solicitação, não é rejeitado automaticamente em uma solicitação de origem cruzada. O veredicto ainda fica registrado em IAntiforgeryValidationFeature, para o código que quiser inspecioná-lo, mas nada impõe isso. CSRF é um vetor de ataque de formulário e de cookie, portanto, endpoints que não processam um formulário enviado pelo navegador geralmente não precisam dessa rejeição. Os endpoints que processam formulários — Razor Pages, views MVC, Blazor SSR e associação de formulário em APIs mínimas — recebem a proteção automaticamente.
Comportamento padrão
O middleware é registrado automaticamente por WebApplication.CreateBuilder e é executado após a autenticação e a autorização. Ele valida cada solicitação usando a implementação registrada ICsrfProtection , que, por padrão, aplica as regras descritas em Como ela funciona. A implementação padrão pode ser substituída; consulte Personalização: implementar ICsrfProtection. Para desativar totalmente o middleware, consulte Desabilitando globalmente.
O resultado é que um aplicativo mínimo com um endpoint para processamento de formulário, como o mostrado a seguir, já está protegido:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/widgets", ([FromForm] Widget w) =>
Results.Created($"/widgets/{w.Id}", w));
app.Run();
Um navegador que faz uma requisição da mesma origem POST /widgets chega ao endpoint normalmente. Um navegador em https://attacker.example.com que envia o mesmo formulário é rejeitado com 400 - Bad Request quando o endpoint faz o binding do formulário, antes que o corpo do manipulador seja executado. Uma curl solicitação sem Sec-Fetch-Site ou Origin é permitida.
Como a rejeição é adiada para os consumidores do formulário, um endpoint que não lê dados de formulário — como uma API JSON que faz o binding do corpo da solicitação a partir de JSON — não é rejeitado automaticamente, mesmo em uma solicitação entre origens. O veredicto ainda é registrado no pedido de código que deseja inspecioná-lo.
O middleware integra-se ao modelo antifalsificação existente:
-
APIs mínimas: Chamar
.DisableAntiforgery()em um endpoint faz com que esse endpoint seja excluído de ambos os middleware baseado em tokens e middleware de proteção contra CSRF. Os mesmos metadados (IAntiforgeryMetadata { RequiresValidation = false }) são verificados por ambos. -
Controladores e ações MVC:
[IgnoreAntiforgeryToken]também exclui o endpoint de ambas as proteções.
Permitir clientes de origens diferentes
O cenário mais comum que exige ação é um cliente baseado em navegador que envia um formulário entre origens — por exemplo, um site em https://app.contoso.com que envia um formulário para uma API em https://api.contoso.com. Esses envios de formulário são negados por padrão porque Sec-Fetch-Site é same-site ou cross-site, em vez de same-origin, e o consumidor do formulário impõe esse veredicto com um 400 - Bad Request.
O middleware CSRF não apresenta sua própria lista de confiança. Ele reutiliza a mesma política CORS que o middleware CORS resolve para o ponto de extremidade: se essa política permitir a solicitação Origin, o middleware CSRF registrará um veredicto permitido para a solicitação.
A política é escolhida para cada endpoint nesta ordem:
-
[EnableCors("api")](MVC) ou.RequireCors("api")(API Mínima) → a política nomeada"api". - Nenhum metadado CORS no ponto de extremidade → a política padrão registrada com
AddDefaultPolicy. - Nenhuma política correspondente (política nomeada não registrada, ausência de política padrão ou
services.AddCors()nunca foi chamado) → nenhuma confiança derivada de CORS. O middleware passa para as regrasSec-Fetch-Sitee Origin-vs-Host.
Um exemplo mínimo usando uma política padrão e um endpoint de API mínima:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
policy.WithOrigins("https://app.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod());
});
var app = builder.Build();
app.UseCors();
app.MapPost("/widgets", ([FromForm] Widget w) =>
Results.Created($"/widgets/{w.Id}", w));
app.Run();
Para uma política nomeada em um único ponto de extremidade:
app.MapPost("/widgets", ([FromForm] Widget w) => Results.Created($"/widgets/{w.Id}", w))
.RequireCors("api");
Aviso
AllowAnyOrigin intencionalmente não é considerado um sinal de confiança de CSRF.
AllowAnyOrigin significa "qualquer navegador pode ler esse recurso", o que é uma preocupação diferente de "qualquer origem pode alterar o estado em nome do usuário". Tratar AllowAnyOrigin como confiável transformaria esse middleware em um no-op para escritas entre origens. Aplicativos que precisam de uma política de CORS de leitura pública combinada com operações de gravação protegidas por CSRF devem listar explicitamente as origens confiáveis para gravação com WithOrigins ou excluir os endpoints de gravação se não dependerem de autenticação baseada em cookie.
[DisableCors] em um ponto de extremidade não é uma desativação de CSRF. Isso ignora a etapa de confiança derivada do CORS, e a solicitação ainda precisa satisfazer as regras Sec-Fetch-Site e Origin-vs-Host. Para desativar a proteção contra CSRF, consulte Desativar a proteção em um endpoint.
Para obter detalhes sobre como configurar o CORS em si—AddCorsAddDefaultPolicy e AddPolicyWithOriginso restante da API do construtor de políticas — consulte Habilitar CORS (Solicitações entre Origens) em ASP.NET Core.
Exclusão de um endpoint
Se um endpoint não for acessível pelo navegador ou estiver protegido por um mecanismo que não seja cookie, como um token Bearer ou uma chave de API, desative-o individualmente em vez de desabilitar o middleware globalmente.
APIs mínimas — chame DisableAntiforgery no endpoint ou grupo:
app.MapPost("/api/webhook", (WebhookPayload p) => Results.Accepted())
.DisableAntiforgery();
Controladores MVC — aplique [IgnoreAntiforgeryToken] à ação ou ao controlador:
[ApiController]
[Route("api/[controller]")]
[IgnoreAntiforgeryToken]
public class WebhookController : ControllerBase
{
[HttpPost]
public IActionResult Post([FromBody] WebhookPayload payload) => Accepted();
}
Qualquer uma das abordagens adiciona IAntiforgeryMetadata { RequiresValidation = false } ao endpoint, que o middleware de CSRF reconhece ao ignorar a validação.
Aviso
Desabilitar a proteção contra CSRF em um endpoint só deve ser feito quando o endpoint não for vulnerável a ataques CSRF — por exemplo, endpoints que não podem ser acessados por um navegador ou que são protegidos por autenticação não baseada em cookie, como tokens bearer ou chaves de API. Não desabilite a proteção contra CSRF em endpoints acessíveis por navegadores que dependem de cookies para autenticação.
Desabilitando globalmente
O middleware pode ser desabilitado em todo o aplicativo usando a DisableCsrfProtection chave de configuração. Isto é uma válvula de escape — prefira exclusões por endpoint.
Em appsettings.json:
{
"DisableCsrfProtection": true
}
Ou como uma variável de ambiente:
ASPNETCORE_DisableCsrfProtection=true
Quando essa chave é definida como true, WebApplication ignora o registro do middleware no pipeline. O ICsrfProtection serviço permanece registrado, portanto, tudo o que o resolve continua funcionando diretamente.
Aviso
O middleware CSRF automático também atende ao requisito de proteção antifalsificação para endpoints que exigem validação, mesmo quando o aplicativo não chama app.UseAntiforgery(). Se um aplicativo depende de antifalsificação, mas não chama app.UseAntiforgery(), desabilitar globalmente o middleware de CSRF ou executar em um host que não foi criado com WebApplication, no qual o middleware não é injetado, deixa esses pontos de extremidade sem middleware de antifalsificação. Uma solicitação para esse ponto de extremidade gera uma exceção. Chame app.UseAntiforgery() nessa configuração.
Suporte ao navegador
Sec-Fetch-Site é compatível com todas as versões atuais de navegadores baseados em Chromium, Firefox e Safari. Para obter uma tabela de compatibilidade autoritativa, consulte a referência de MDN para Sec-Fetch-Site.
Navegadores mais antigos, anteriores ao Fetch Metadata, não enviam Sec-Fetch-Site. Para esses clientes, o middleware volta a comparar o cabeçalho Origin com o esquema e o host da solicitação. Os navegadores enviam Origin em solicitações de gravação de origem cruzada há muitos anos, portanto esse fallback abrange essencialmente todo o tráfego de navegadores legados.
Clientes não baseados em navegador —curl, Postman, aplicativos móveis e clientes servidor a servidor— normalmente não enviam nem Sec-Fetch-Site nem Origin. Essas solicitações são permitidas porque o CSRF é um vetor de ataque somente do navegador que depende do navegador anexar automaticamente credenciais de ambiente, como cookies. Um cliente que não é navegador que deseja atacar a API não precisa de CSRF; ele pode simplesmente chamar a API diretamente com as credenciais que ela possui.
Personalização: implementar ICsrfProtection
A lógica de decisão está por trás de uma interface com um único método:
namespace Microsoft.AspNetCore.Antiforgery;
public interface ICsrfProtection
{
ValueTask<CsrfProtectionResult> ValidateAsync(HttpContext context);
}
Para substituir a implementação padrão, registre um singleton no DI. Como a estrutura usa TryAddSingleton, uma chamada explícita AddSingleton substitui o padrão:
builder.Services.AddSingleton<ICsrfProtection, AllowlistCsrfProtection>();
Uma implementação personalizada é útil quando o modelo de confiança não se ajusta ao CORS, por exemplo, quando uma lista de permissões fixa de origens de parceiro é preferencial ou quando regras mais rígidas são necessárias:
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Http;
public sealed class AllowlistCsrfProtection : ICsrfProtection
{
private static readonly HashSet<string> SafeMethods =
new(StringComparer.OrdinalIgnoreCase) { "GET", "HEAD", "OPTIONS", "TRACE" };
private static readonly HashSet<string> TrustedOrigins =
new(StringComparer.OrdinalIgnoreCase)
{
"https://app.contoso.com",
"https://admin.contoso.com",
};
public ValueTask<CsrfProtectionResult> ValidateAsync(HttpContext context)
{
if (SafeMethods.Contains(context.Request.Method))
{
return ValueTask.FromResult(CsrfProtectionResult.Allowed());
}
var origin = context.Request.Headers.Origin.ToString();
var allowed = !string.IsNullOrEmpty(origin) && TrustedOrigins.Contains(origin);
return ValueTask.FromResult(
allowed ? CsrfProtectionResult.Allowed() : CsrfProtectionResult.Denied());
}
}
O middleware ainda respeita .DisableAntiforgery() / [IgnoreAntiforgeryToken] independentemente de qual implementação é registrada– a recusa é tratada pelo middleware em si antes ValidateAsync de ser chamada.
Interação com a antifalsificação baseada em token
As duas defesas CSRF visam camadas diferentes e foram projetadas para coexistir. Eles também compartilham a mesma funcionalidade de solicitação: ambos registram seu resultado em IAntiforgeryValidationFeature, e os consumidores de formulário aplicam qualquer veredito presente.
| Aspeto | Baseado em token AntiforgeryMiddleware |
Middleware de proteção automática contra CSRF |
|---|---|---|
| Introduzida | ASP.NET Core 2.0+ | .NET 11 |
| Activation | Aceitar via app.UseAntiforgery() (ou implicitamente porAddMvc / MapRazorPages / AddRazorComponents ) |
Injetado automaticamente por WebApplication.CreateBuilder |
| Valida | Token sincronizado (campo de formulário + par cookie) |
Sec-Fetch-Site
/
Origin Cabeçalhos |
| Requires | Visão geral da Proteção de Dados ASP.NET Core para criptografia de token | Sem tokens, sem estado |
| Escopo do navegador | Todos os navegadores que enviam cookies | Todos os navegadores modernos; Origin alternativa para navegadores legados |
| Recusa por ponto de extremidade | .DisableAntiforgery() / [IgnoreAntiforgeryToken] |
Mesmo : ambos respeitam os mesmos metadados |
O middleware baseado em token protege especificamente contra o padrão de ataque CSRF clássico no qual um site mal-intencionado dispara um formulário POST para um site vulnerável usando os cookies ambientes do usuário. O middleware CSRF automático aborda a mesma ameaça na camada HTTP usando metadados fornecidos pelo navegador. Ambos podem estar ativos no mesmo endpoint, e muitos aplicativos se beneficiarão da defesa em profundidade:
- Razor Páginas, MVC e Blazor aplicativos SSR que já usam o sistema de token ganham uma verificação baseada em cabeçalho que é executada antes da validação do token, sem alterar o fluxo de token.
-
Aplicativos de API mínima que fazem associação a formulários passam a ter um comportamento padrão útil sem precisar chamar
app.UseAntiforgery()nem passarIAntiforgerypelos pontos de extremidade. - APIs chamadas por SPAs de origem cruzada podem contar com esse middleware combinado com uma lista de permissões do CORS e ignorar totalmente o sistema de tokens se a API nunca fornecer formulários HTML.
O middleware CSRF automático substitui o sistema baseado em tokens em muitos cenários, pois ambos protegem os mesmos endpoints de processamento de formulários. Mantenha o sistema baseado em token quando:
- O aplicativo deve dar suporte a navegadores que não enviam
Sec-Fetch-Site. Consulte o suporte do Navegador. - O aplicativo usa IAntiforgeryAdditionalDataProvider para armazenar e recuperar dados extras dentro do token.
- Um requisito de conformidade ou revisão de segurança especifica a defesa do token como uma camada independente.
Para obter detalhes sobre o sistema baseado em token, incluindo integração de formulários, fluxos AJAX, configuração via AntiforgeryOptionse IAntiforgery APIs, consulte Antiforgery em ASP.NET Core.
A validação de token tem precedência
Quando um aplicativo chama app.UseAntiforgery(), o middleware baseado em tokens é executado após o middleware CSRF automático. O middleware do token limpa qualquer decisão registrada pelo middleware CSRF e a substitui pelo resultado da validação do token. O resultado do token é autoritativo:
- Uma solicitação que o middleware CSRF marcou como inválida torna-se válida se contiver um token válido.
- Uma solicitação permitida pelo middleware CSRF é marcada como inválida se seu token estiver ausente ou for inválido.
Essa ordenação significa que os aplicativos que usam o sistema de tokens veem o mesmo comportamento de ponta a ponta que tinham antes do middleware automático existir, enquanto os aplicativos que não usam tokens retornam ao veredito do middleware CSRF.
Blazor renderização estática do lado do servidor
Blazor endpoints estáticos de renderização no lado do servidor (SSR) participam do mesmo modelo de adiamento. O endpoint Razor Components confia no veredito registrado em IAntiforgeryValidationFeature pelo middleware anterior e retorna 400 - Bad Request para um envio de formulário somente quando esse veredito é inválido. O ponto de extremidade não valida mais a solicitação em si.
O comportamento depende de qual middleware foi executado:
- Os aplicativos que chamam
app.UseAntiforgery()não são alterados. O middleware baseado em tokens valida cada solicitação, e tokens antifalsificação são gerados para os formulários renderizados, como antes. - Os aplicativos que não chamam
app.UseAntiforgery()são protegidos pelo middleware automático de CSRF, em vez disso. Nessa configuração, o endpoint ignora a geração do token anti-falsificação porque não há nenhum middleware para validar o token em uma solicitação subsequente.
Esta é uma mudança de comportamento no SSR estático que anteriormente removia app.UseAntiforgery(): agora, ele passa a ser protegido pelo middleware de CSRF, em vez de ficar desprotegido, e deixa de emitir tokens antifalsificação. Para obter diretrizes de migração, consulte Migrar de ASP.NET Core no .NET 10 para ASP.NET Core no .NET 11. Para o aviso formal sobre alteração significativa, consulte Blazor a renderização no servidor adia a validação antifalsificação para o middleware.
Troubleshooting
Sintoma: As solicitações da mesma origem feitas em um navegador são bem-sucedidas, mas os envios de formulário de origem cruzada retornam 400 - Bad Request sem corpo da resposta.
Causa: O middleware de CSRF registrou uma decisão inválida para a solicitação entre origens diferentes, e um componente de processamento de formulário, como uma ação MVC, uma vinculação de formulário de API Minimal ou uma postagem de formulário SSR Blazor, aplicou essa decisão com um 400 - Bad Request. Esse é o comportamento padrão esperado para endpoints que processam formulários.
Resolução: Escolha um dos seguintes, dependendo do cenário:
- Se a origem da chamada for conhecida e confiável, permita-a por meio do CORS.
- Se o endpoint não for acessível pelo navegador ou usar autenticação diferente de cookie, exclua-o com
.DisableAntiforgery()ou[IgnoreAntiforgeryToken]. - Se todo o aplicativo precisar não participar (por exemplo, durante um período de migração), desative globalmente.
Diagnóstico: O middleware registra todos os resultados inválidos no nível Debug na categoria Microsoft.AspNetCore.Antiforgery.CsrfProtectionMiddleware, com o nome de evento CsrfValidationFailed. Habilite Debug o registro em log para essa categoria em appsettings.Development.json:
{
"Logging": {
"LogLevel": {
"Microsoft.AspNetCore.Antiforgery.CsrfProtectionMiddleware": "Debug"
}
}
}
Um veredicto gravado aparece no log como:
dbug: Microsoft.AspNetCore.Antiforgery.CsrfProtectionMiddleware[1]
Cross-origin CSRF protection marked request POST /widgets from origin 'https://attacker.example.com' as invalid.
Reproduzindo localmente: Use curl com um cabeçalho Origin explícito para simular uma solicitação de navegador entre origens para um endpoint de formulário:
curl -i -X POST https://localhost:{PORT}/widgets \
-H "Origin: https://attacker.example.com" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "name=test"
Substitua {PORT} pela porta HTTPS local do aplicativo. O 400 - Bad Request é observado porque o endpoint vincula o formulário, o que aplica a decisão registrada. Um endpoint que não é de formulário retorna sua resposta normal porque nada lê o resultado. Sem o Origin cabeçalho, a mesma solicitação é permitida porque curl também não envia Sec-Fetch-Site e uma solicitação com nenhum dos cabeçalhos é tratada como um cliente que não é navegador.
O sistema antifalsificação baseado em tokens descrito no restante do artigo é anterior a esse middleware e permanece disponível. Para a maioria dos aplicativos, a proteção automática é suficiente por conta própria. Para obter diretrizes sobre quando manter o sistema baseado em token e como migrar, consulte Migrar de ASP.NET Core em .NET 10 para ASP.NET Core no .NET 11.
Antifalsificação no ASP.NET Core
Aviso
ASP.NET Core implementa antifalsificação por meio da Proteção de Dados do ASP.NET Core. A pilha de proteção de dados deve ser configurada para funcionar em um farm de servidores. Para obter mais informações, consulte Como configurar a proteção de dados.
O middleware antifalsificação é adicionado ao contêiner de Injeção de dependência quando uma das seguintes APIs é chamada em Program.cs:
Para obter mais informações, consulte Antifalsificação com APIs mínimas.
O FormTagHelper injeta tokens antifalsificação em elementos de formulário HTML. A marcação a seguir em um arquivo Razor gera tokens antifalsificação automaticamente:
<form method="post">
<!-- ... -->
</form>
Da mesma forma, IHtmlHelper.BeginForm gera tokens antifalsificação por padrão se o método do formulário não for GET.
A geração automática de tokens antifalsificação para elementos de formulário HTML ocorre quando a marca <form> contém o atributo method="post" e alguma das seguintes alternativas sejam verdadeiras:
- O atributo de ação está vazio (
action=""). - O atributo de ação não foi fornecido (
<form method="post">).
A geração automática de tokens antifalsificação para elementos de formulário HTML pode ser desabilitada:
Desabilite explicitamente os tokens de antifalsificação com o atributo
asp-antiforgery.<form method="post" asp-antiforgery="false"> <!-- ... --> </form>O elemento formulário é recusado nos Auxiliares de Marca usando o símbolo ! recusar do Auxiliar de Marca:
<!form method="post"> <!-- ... --> </!form>Remova o
FormTagHelperda visualização. OFormTagHelperpode ser removido de uma visão adicionando a seguinte diretiva à visão Razor:@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
Observação
As páginas são automaticamente protegidas contra XSRF/CSRF. Para obter mais informações, consulte XSRF/CSRF e Razor Páginas.
A abordagem mais comum para se defender contra ataques CSRF é usar o STP (padrão de token do sincronizador). O STP é usado quando o usuário solicita uma página com dados de formulário:
- O servidor envia um token associado à identidade do usuário atual para o cliente.
- O cliente envia de volta o token para o servidor para verificação.
- Se o servidor receber um token que não corresponda à identidade do usuário autenticado, a solicitação será rejeitada.
O token é exclusivo e imprevisível. O token também pode ser usado para garantir o sequenciamento adequado de uma série de solicitações (por exemplo, garantindo a sequência de solicitações de: página 1 > página 2 > página 3). Todos os formulários em ASP.NET Core modelos MVC e Páginas Razor geram tokens antifalsificação. O seguinte par de exemplos de modo de exibição gera tokens antifalsificação:
<form asp-action="Index" asp-controller="Home" method="post">
<!-- ... -->
</form>
@using (Html.BeginForm("Index", "Home"))
{
<!-- ... -->
}
Adicione explicitamente um token antifalsificação a um <form> elemento sem usar Auxiliares de Marca com o auxiliar HTML @Html.AntiForgeryToken :
<form asp-action="Index" asp-controller="Home" method="post">
@Html.AntiForgeryToken()
<!-- ... -->
</form>
Em cada um dos casos anteriores, o ASP.NET Core adiciona um campo de formulário oculto semelhante ao seguinte exemplo:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
O ASP.NET Core inclui três filtros para trabalhar com tokens antifalsificação:
Antifalsificação com AddControllers
Chamar AddControllersnão habilita tokens antifalsificação. AddControllersWithViews deve ser chamado para ter suporte interno a tokens antifalsificação.
Várias guias do navegador e o padrão de token do sincronizador
Não há suporte para várias guias abertas com usuários diferentes conectados ou uma guia aberta conectada como anônima.
Configurar antifalsificação com AntiforgeryOptions
Personalize AntiforgeryOptions no arquivo Program do aplicativo:
builder.Services.AddAntiforgery(options =>
{
// Set Cookie properties using CookieBuilder properties†.
options.FormFieldName = "AntiforgeryFieldname";
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
options.SuppressXFrameOptionsHeader = false;
});
Defina as propriedades cookie antifalsificação usando as propriedades da classe CookieBuilder, conforme mostrado na tabela a seguir.
| Opção | Descrição |
|---|---|
| Cookie | Determina as configurações usadas para criar os cookies antifalsificação. |
| FormFieldName | O nome do campo de formulário oculto usado pelo sistema antifalsificação para renderizar tokens antifalsificação em modos de exibição. |
| HeaderName | O nome do cabeçalho usado pelo sistema antifalsificação. Se null, o sistema considerará apenas os dados do formulário. |
| SuppressXFrameOptionsHeader | Especifica se a geração do X-Frame-Options cabeçalho deve ser suprimida. Por padrão, o cabeçalho é gerado com um valor de "SAMEORIGIN". Assume o padrão de false. |
Alguns navegadores não permitem que endereços inseguros definam cookies com a marcação 'secure' ou sobrescrevam cookies cuja marcação 'secure' foi configurada (para obter mais informações, consulte A modificação preterida de cookies 'seguros' de origens não seguras). Como a mistura dos pontos de extremidade seguros e inseguros é um cenário comum em aplicativos, o ASP.NET Core relaxa a restrição à política de segurança em alguns cookies, como a antifalsificação cookie, definindo o cookie do SecurePolicy como CookieSecurePolicy.None. Mesmo que roube uma antifalsificação cookie, um usuário mal-intencionado também deve roubar o token de antifalsificação normalmente enviado por meio de um campo de formulário (mais comum) ou um cabeçalho de solicitação à parte (menos comum) mais a autenticação cookie. Cookies relacionados à autenticação ou autorização usam uma política mais forte que CookieSecurePolicy.None.
Você também pode proteger a antifalsificação cookie em ambientes que não sejam Development usando SSL (Secure Sockets Layer), somente via HTTPS, com a seguinte configuração de propriedade AntiforgeryOptions.Cookie no arquivo Program do aplicativo:
if (!builder.Environment.IsDevelopment())
{
builder.Services.AddAntiforgery(o =>
{
o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
}
Para obter mais informações, consulte CookieAuthenticationOptions.
Gerar tokens antifalsificação com IAntiforgery
IAntiforgery fornece a API para configurar recursos antifalsificação.
IAntiforgery pode ser solicitado no Program.cs usando WebApplication.Services. O exemplo a seguir usa o middleware da página inicial do aplicativo para gerar um token antifalsificação e enviá-lo na resposta como um cookie:
app.UseRouting();
app.UseAuthorization();
var antiforgery = app.Services.GetRequiredService<IAntiforgery>();
app.Use((context, next) =>
{
var requestPath = context.Request.Path.Value;
if (string.Equals(requestPath, "/", StringComparison.OrdinalIgnoreCase)
|| string.Equals(requestPath, "/index.html", StringComparison.OrdinalIgnoreCase))
{
var tokenSet = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokenSet.RequestToken!,
new CookieOptions { HttpOnly = false });
}
return next(context);
});
O exemplo anterior define um cookie nomeado XSRF-TOKEN. O cliente pode ler esse cookie e fornecer seu valor como um cabeçalho anexado a solicitações AJAX. Por exemplo, o Angular inclui proteção XSRF interna que lê um cookie nomeado XSRF-TOKEN por padrão.
Exigir validação antifalsificação
O filtro de ação ValidateAntiForgeryToken pode ser aplicado a uma ação individual, a um controlador ou globalmente. As solicitações feitas às ações que têm esse filtro aplicado são bloqueadas, a menos que a solicitação inclua um token antifalsificação válido:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index()
{
// ...
return RedirectToAction();
}
O atributo ValidateAntiForgeryToken exige um token para solicitações para os métodos de ação que marca, incluindo solicitações HTTP GET. Se o atributo ValidateAntiForgeryToken for aplicado entre os controladores do aplicativo, ele poderá ser substituído pelo atributo IgnoreAntiforgeryToken.
Validar automaticamente tokens antifalsificação somente para métodos HTTP não seguros
Em vez de aplicar amplamente o atributo ValidateAntiForgeryToken e substituí-lo por atributos IgnoreAntiforgeryToken, o atributo AutoValidateAntiforgeryToken pode ser usado. Esse atributo funciona de forma idêntica ao atributo ValidateAntiForgeryToken, mas ele não requer tokens para solicitações feitas usando os seguintes métodos HTTP:
- GET
- HEAD
- OPÇÕES
- TRACE
É recomendável usar amplamente AutoValidateAntiforgeryToken para cenários que não são de API. Esse atributo garante que as ações POST sejam protegidas por padrão. A alternativa é ignorar, por padrão, os tokens antifalsificação, a menos que ValidateAntiForgeryToken seja aplicado a métodos de ação individuais. Nesse cenário, é mais provável que um método de ação POST seja deixado desprotegido por engano, deixando o aplicativo vulnerável a ataques CSRF. Todos os POSTs devem enviar o token antifalsificação.
As APIs não têm um mecanismo automático para enviar a partecookie que não é do token. A implementação provavelmente depende da implementação do código do cliente. Mostramos alguns exemplos abaixo:
Exemplo de nível de classe:
[AutoValidateAntiforgeryToken]
public class HomeController : Controller
Exemplo global:
builder.Services.AddControllersWithViews(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
Substituir atributos antifalsificação globais ou de controlador
O filtro IgnoreAntiforgeryToken é usado para eliminar a necessidade de um token antifalsificação para uma determinada ação (ou controlador). Quando aplicado, esse filtro substitui os filtros ValidateAntiForgeryToken e AutoValidateAntiforgeryToken especificados em um nível superior (globalmente ou em um controlador).
[IgnoreAntiforgeryToken]
public IActionResult IndexOverride()
{
// ...
return RedirectToAction();
}
Atualizar tokens após a autenticação
Os tokens devem ser atualizados depois que o usuário é autenticado redirecionando o usuário para um modo de exibição ou para a página de Páginas Razor.
JavaScript, AJAX e SPAs
Em aplicativos tradicionais baseados em HTML, tokens antifalsificação são passados para o servidor usando campos de formulário ocultos. Em SPAs e aplicativos modernos baseados em JavaScript, muitas solicitações são feitas programaticamente. Essas solicitações AJAX podem usar outras técnicas, como cabeçalhos de solicitação ou cookies, para enviar o token.
Se cookies forem usados para armazenar tokens de autenticação e autenticar solicitações de API no servidor, o CSRF é um problema em potencial. Se o armazenamento local for usado para armazenar o token, a vulnerabilidade CSRF poderá ser atenuada porque os valores do armazenamento local não são enviados automaticamente para o servidor a cada solicitação. Usar o armazenamento local para armazenar o token antifalsificação no cliente e enviar o token como um cabeçalho de solicitação é uma abordagem recomendada.
Blazor
Para obter mais informações, confira autenticação e autorização do AsP.NET Core Blazor.
JavaScript
Usando JavaScript com modos de exibição, o token pode ser criado usando um serviço de dentro da exibição. Injete o serviço IAntiforgery na exibição e chame GetAndStoreTokens:
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery
@{
ViewData["Title"] = "JavaScript";
var requestToken = Antiforgery.GetAndStoreTokens(Context).RequestToken;
}
<input id="RequestVerificationToken" type="hidden" value="@requestToken" />
<button id="button" class="btn btn-primary">Submit with Token</button>
<div id="result" class="mt-2"></div>
@section Scripts {
<script>
document.addEventListener("DOMContentLoaded", () => {
const resultElement = document.getElementById("result");
document.getElementById("button").addEventListener("click", async () => {
const response = await fetch("@Url.Action("FetchEndpoint")", {
method: "POST",
headers: {
RequestVerificationToken:
document.getElementById("RequestVerificationToken").value
}
});
if (response.ok) {
resultElement.innerText = await response.text();
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
});
});
</script>
}
O exemplo anterior usa JavaScript para ler o valor do campo oculto para o cabeçalho POST do AJAX.
Essa abordagem elimina a necessidade de lidar diretamente com a configuração de cookies do servidor ou de lê-los a partir do cliente. No entanto, quando não for possível injetar o serviço IAntiforgery, use JavaScript para acessar tokens em cookies:
- Tokens de acesso em uma solicitação adicional para o servidor, normalmente
same-origin. - Utilize o conteúdo do cookie para criar um cabeçalho com o valor do token.
Supondo que o script envie o token em um cabeçalho de solicitação chamado X-XSRF-TOKEN, configure o serviço antifalsificação para procurar o cabeçalho X-XSRF-TOKEN:
builder.Services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
O exemplo a seguir adiciona um ponto de extremidade protegido que grava o token de solicitação em um JavaScript legível cookie:
app.UseAuthorization();
app.MapGet("antiforgery/token", (IAntiforgery forgeryService, HttpContext context) =>
{
var tokens = forgeryService.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken!,
new CookieOptions { HttpOnly = false });
return Results.Ok();
}).RequireAuthorization();
O exemplo a seguir usa JavaScript para fazer uma solicitação AJAX para obter o token e fazer outra solicitação com o cabeçalho apropriado:
var response = await fetch("/antiforgery/token", {
method: "GET",
headers: { "Authorization": authorizationToken }
});
if (response.ok) {
// https://developer.mozilla.org/docs/web/api/document/cookie
const xsrfToken = document.cookie
.split("; ")
.find(row => row.startsWith("XSRF-TOKEN="))
.split("=")[1];
response = await fetch("/JavaScript/FetchEndpoint", {
method: "POST",
headers: { "X-XSRF-TOKEN": xsrfToken, "Authorization": authorizationToken }
});
if (response.ok) {
resultElement.innerText = await response.text();
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
Observação
Quando o token antifalsificação é fornecido no cabeçalho da solicitação e no conteúdo do formulário, somente o token no cabeçalho é validado.
Antifalsificação com APIs Minimalistas
Chame AddAntiforgery e UseAntiforgery(IApplicationBuilder) registre serviços antiforgery no DI. Tokens antifalsificação são usados para atenuar ataques de falsificação de solicitação entre sites.
var builder = WebApplication.CreateBuilder();
builder.Services.AddAntiforgery();
var app = builder.Build();
app.UseAntiforgery();
app.MapGet("/", () => "Hello World!");
app.Run();
O middleware antifalsificação:
- Nãoexecuta a curto-circuito o restante do pipeline de solicitação.
- Define o IAntiforgeryValidationFeature no HttpContext.Features da solicitação atual.
O token antifalsificação só será validado se:
- O ponto de extremidade contém metadados implementando IAntiforgeryMetadata onde
RequiresValidation=true. - O método HTTP associado ao ponto de extremidade é um método HTTP relevante do tipo POST, PUT ou PATCH.
- A solicitação está associada a um ponto de extremidade válido.
O middleware de antifalsificação não interrompe o pipeline de requisição. O código do ponto de extremidade sempre é executado, mesmo que a validação de token falhe. Para observar o resultado da validação do token, resolva o IAntiforgeryValidationFeature de HttpContext.Features e inspecione a propriedade IsValid ou a propriedade Error para obter detalhes de falha. Essa abordagem é útil quando pontos de extremidade exigem identificação personalizada para validação antifalsificação com falha.
Observação: Quando habilitado manualmente, o middleware antifalsificação deve ser executado após o middleware de autenticação e autorização para impedir a leitura de dados do formulário quando o usuário não for autenticado.
Por padrão, APIs mínimas que aceitam dados de formulário exigem validação de token antiforgery e falham antes de executar o código do aplicativo se a validação antiforgeria não for bem-sucedida.
Considere o seguinte método GenerateForm:
public static string GenerateForm(string action,
AntiforgeryTokenSet token, bool UseToken=true)
{
string tokenInput = "";
if (UseToken)
{
tokenInput = $@"<input name=""{token.FormFieldName}""
type=""hidden"" value=""{token.RequestToken}"" />";
}
return $@"
<html><body>
<form action=""{action}"" method=""POST"" enctype=""multipart/form-data"">
{tokenInput}
<input type=""text"" name=""name"" />
<input type=""date"" name=""dueDate"" />
<input type=""checkbox"" name=""isCompleted"" />
<input type=""submit"" />
</form>
</body></html>
";
}
O código anterior tem três argumentos, a ação, o token anti-falsificação e um bool indicando se o token deve ser usado.
Considere o seguinte exemplo:
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder();
builder.Services.AddAntiforgery();
var app = builder.Build();
app.UseAntiforgery();
// Pass token
app.MapGet("/", (HttpContext context, IAntiforgery antiforgery) =>
{
var token = antiforgery.GetAndStoreTokens(context);
return Results.Content(MyHtml.GenerateForm("/todo", token), "text/html");
});
// Don't pass a token, fails
app.MapGet("/SkipToken", (HttpContext context, IAntiforgery antiforgery) =>
{
var token = antiforgery.GetAndStoreTokens(context);
return Results.Content(MyHtml.GenerateForm("/todo",token, false ), "text/html");
});
// Post to /todo2. DisableAntiforgery on that endpoint so no token needed.
app.MapGet("/DisableAntiforgery", (HttpContext context, IAntiforgery antiforgery) =>
{
var token = antiforgery.GetAndStoreTokens(context);
return Results.Content(MyHtml.GenerateForm("/todo2", token, false), "text/html");
});
app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));
app.MapPost("/todo2", ([FromForm] Todo todo) => Results.Ok(todo))
.DisableAntiforgery();
app.Run();
class Todo
{
public required string Name { get; set; }
public bool IsCompleted { get; set; }
public DateTime DueDate { get; set; }
}
public static class MyHtml
{
public static string GenerateForm(string action,
AntiforgeryTokenSet token, bool UseToken=true)
{
string tokenInput = "";
if (UseToken)
{
tokenInput = $@"<input name=""{token.FormFieldName}""
type=""hidden"" value=""{token.RequestToken}"" />";
}
return $@"
<html><body>
<form action=""{action}"" method=""POST"" enctype=""multipart/form-data"">
{tokenInput}
<input type=""text"" name=""name"" />
<input type=""date"" name=""dueDate"" />
<input type=""checkbox"" name=""isCompleted"" />
<input type=""submit"" />
</form>
</body></html>
";
}
}
No código anterior, posta para:
-
/todoexige um token antifalsificação válido. -
/todo2não requer um token antifalsificação válido porque DisableAntiforgery é chamado.
app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));
app.MapPost("/todo2", ([FromForm] Todo todo) => Results.Ok(todo))
.DisableAntiforgery();
Aviso
A chamada de .DisableAntiforgery() desativa a proteção CSRF (solicitação intersite forjada) para o ponto de extremidade. Isso só deve ser usado quando um endpoint não está vulnerável a ataques CSRF, como:
- Pontos de extremidade que não podem ser chamados de um navegador (por exemplo, APIs internas)
- Pontos de extremidade protegidos com autenticação não baseada em cookie (por exemplo, tokens de portador ou chaves de API)
- Endpoints internos ou de infraestrutura que não dependem de cookies de usuário
Não desabilite a validação antifalsificação para endpoints acessíveis pelo navegador que dependem de cookies para autenticação ou que processam dados de formulário submetidos pelo usuário, pois isso expõe seu aplicativo a ataques CSRF.
Um POST para:
-
/tododo formulário gerado pelo ponto de extremidade/é bem-sucedido porque o token antifalsificação é válido. -
/tododo formulário gerado pelo/SkipTokenfalha porque a antifalsificação não está incluída. -
/todo2do formulário gerado pelo ponto de extremidade/DisableAntiforgeryé bem-sucedido porque o token antifalsificação é não é necessário.
app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));
app.MapPost("/todo2", ([FromForm] Todo todo) => Results.Ok(todo))
.DisableAntiforgery();
Quando um formulário é enviado sem um token antifalsificação válido:
- No ambiente
Development, uma exceção é lançada. -
ProductionNo ambiente, uma mensagem é registrada em log.
Limitações do método HTTP e interação HttpMethodOverrideMiddleware
Para a abordagem de antifalsificação baseada em middleware, AntiforgeryMiddleware e UseAntiforgery() validam tokens antifalsificação somente para solicitações HTTP POST, PUT e PATCH. Outros métodos HTTP, como DELETE, não são validados automaticamente.
Para validar tokens antifalsificação para outros métodos HTTP, resolva IAntiforgery de DI e chame ValidateRequestAsync ou IsRequestValidAsync explicitamente:
app.MapDelete("/item/{id}", async (int id, IAntiforgery antiforgery, HttpContext context) =>
{
await antiforgery.ValidateRequestAsync(context);
// Process the DELETE request
});
Aviso
Quando HttpMethodOverrideMiddleware é configurado com FormFieldName (modo de campo de formulário) e colocado antes de AntiforgeryMiddleware, uma solicitação POST pode ser substituída por DELETE (ou outro método não validado). Como AntiforgeryMiddleware valida apenas POST, PUT e PATCH, a solicitação substituída ignora a validação antiforgeria.
Para proteger estes endpoints:
- Prefira posicionar
HttpMethodOverrideMiddlewareapós a validação antifalsificação quando o pipeline permitir. - Evite substituições do campo de formulário para pontos de extremidade que dependam de validação antifalsificação.
- Se a substituição do campo de formulário precisar ser executada primeiro, valide explicitamente o token antifalsificação usando
IAntiforgery.ValidateRequestAsync.
Para obter detalhes de configuração, consulte ASP.NET Core middleware.
Autenticação do Windows e cookies antifalsificação
Ao utilizar a autenticação do Windows, os pontos de extremidade do aplicativo devem ser protegidos contra ataques CSRF da mesma maneira que se faz com cookies. O navegador envia implicitamente o contexto de autenticação para o servidor e os endpoints precisam ser protegidos contra ataques CSRF.
Estender a antifalsificação
O tipo IAntiforgeryAdditionalDataProvider permite que os desenvolvedores estendam o comportamento do sistema anti-CSRF ao arredondar dados adicionais em cada token. O método GetAdditionalData é chamado sempre que um token de campo é gerado e o valor retornado é inserido no token gerado. Um implementador pode retornar um timestamp, um nonce ou qualquer outro valor e, em seguida, chamar ValidateAdditionalData para validar esse dado quando o token for validado. O nome de usuário do cliente já está inserido nos tokens gerados, portanto, não é necessário incluir essas informações. Se um token incluir dados complementares, mas nenhum IAntiForgeryAdditionalDataProvider estiver configurado, os dados complementares não serão validados.
Recursos adicionais
A solicitação entre sites forjada (também conhecida como XSRF ou CSRF) é um ataque contra aplicativos Web hospedados, no qual um site mal-intencionado pode influenciar a interação entre um navegador cliente e um aplicativo Web que confia nesse navegador. Os ataques são possíveis porque os navegadores enviam automaticamente alguns tipos de tokens de autenticação com cada solicitação a um site. Essa forma de exploração também é conhecida como ataque de um clique ou sequestro de sessão, pois o ataque aproveita a sessão autenticada anteriormente pelo usuário.
Um exemplo de ataque CSRF:
Um usuário faz login no
www.good-banking-site.example.comusando a autenticação de formulários. O servidor autentica o usuário e emite uma resposta que inclui uma autenticação cookie. O site é vulnerável a ataques porque confia em qualquer solicitação recebida com uma autenticação cookieválida.O usuário visita um site mal-intencionado,
www.bad-crook-site.example.com.O site mal-intencionado,
www.bad-crook-site.example.com, contém um formulário HTML semelhante ao seguinte exemplo:<h1>Congratulations! You're a Winner!</h1> <form action="https://www.good-banking-site.example.com/api/account" method="post"> <input type="hidden" name="Transaction" value="withdraw" /> <input type="hidden" name="Amount" value="1000000" /> <input type="submit" value="Click to collect your prize!" /> </form>Observe que o formulário publica
actionno site vulnerável, não no site mal-intencionado. Essa é a parte "entre sites" do CSRF.O usuário seleciona o botão Enviar. O navegador faz a solicitação e inclui automaticamente a autenticação cookie para o domínio solicitado,
www.good-banking-site.example.com.A solicitação é executada no servidor
www.good-banking-site.example.comcom o contexto de autenticação do usuário e pode executar qualquer ação que um usuário autenticado tenha permissão para executar.
Além do cenário em que o usuário seleciona o botão para enviar o formulário, o site mal-intencionado pode:
- Executar um script que envia automaticamente o formulário.
- Enviar o envio do formulário como uma solicitação AJAX.
- Ocultar o formulário usando CSS.
Esses cenários alternativos não exigem nenhuma ação ou entrada do usuário além de visitar inicialmente o site mal-intencionado.
O uso de HTTPS não impede um ataque CSRF. O site malicioso pode enviar uma solicitação https://www.good-banking-site.example.com/ tão facilmente quanto uma solicitação insegura.
Alguns ataques visam pontos de extremidade que respondem a solicitações GET, nesse caso, uma marca de imagem pode ser usada para executar a ação. Essa forma de ataque é comum em sites de fórum que permitem imagens, mas bloqueiam JavaScript. Aplicativos que alteram o estado em solicitações GET, em que variáveis ou recursos são alterados, são vulneráveis a ataques mal-intencionados. Solicitações GET que alteram o estado são inseguras. Uma prática recomendada é nunca alterar o estado em uma solicitação GET.
Ataques CSRF são possíveis contra aplicativos Web que usam cookies para autenticação porque:
- Os navegadores armazenam cookies emitidos por um aplicativo Web.
- Os cookies armazenados incluem cookies de sessões de usuários autenticados.
- Os navegadores enviam todos os os cookies associados a um domínio para o aplicativo Web a cada solicitação, independentemente de como a solicitação para o aplicativo foi gerada no navegador.
Entretanto, os ataques CSRF não se limitam à exploração de cookies. Por exemplo, a autenticação Básica e Digest também são vulneráveis. Depois que um usuário entra com a autenticação Básica ou Digest, o navegador envia automaticamente as credenciais até que a sessão termine.
Nesse contexto, a sessão refere-se à sessão do lado do cliente durante a qual o usuário é autenticado. Não está relacionado às sessões no lado do servidor nem ao middleware de sessão do ASP.NET Core.
Os usuários podem se proteger contra vulnerabilidades CSRF ao tomar precauções:
- Saia dos aplicativos Web quando terminar de usá-los.
- Limpe os os cookies do navegador periodicamente.
No entanto, as vulnerabilidades CSRF são fundamentalmente um problema com o aplicativo Web, não com o usuário final.
Conceitos básicos sobre autenticação
A autenticação baseada em Cookie é uma forma popular de autenticação. Os sistemas de autenticação baseados em token estão crescendo em popularidade, especialmente para Aplicativos de Página Única (SPAs).
Autenticação baseada em Cookie
Quando um usuário se autentica usando seu nome de usuário e senha, ele recebe um token, contendo um tíquete de autenticação que pode ser usado para autenticação e autorização. O token é armazenado como um cookie que é enviado com cada solicitação que o cliente faz. A geração e a validação deste cookie são realizadas pelo cookie middleware de autenticação. O middleware serializa uma entidade de segurança de usuário em um criptografado cookie. Em solicitações subsequentes, o middleware valida o cookie, recria a entidade de segurança e atribui a entidade de segurança à propriedade HttpContext.User.
Autenticação baseada em token
Quando um usuário é autenticado, um token é emitido para ele (não um token antifalsificação). O token contém informações do usuário na forma de declarações ou um token de referência que aponta o aplicativo para o estado do usuário mantido no aplicativo. Quando um usuário tenta acessar um recurso que requer autenticação, o token é enviado para o aplicativo com um cabeçalho de autorização extra na forma de um token de portador. Essa abordagem torna o aplicativo sem estado. Em cada solicitação subsequente, o token é passado na solicitação de validação do lado do servidor. Esse token não é criptografado, ele é codificado. No servidor, o token é decodificado para acessar suas informações. Para enviar o token em solicitações subsequentes, armazene o token no armazenamento local do navegador. Colocar um token no armazenamento local do navegador e recuperá-lo e usá-lo como um token de portador fornece proteção contra ataques CSRF. No entanto, se o aplicativo estiver vulnerável à injeção de script por meio do XSS ou de um arquivo javascript externo comprometido, um invasor cibernético poderá recuperar qualquer valor do armazenamento local e enviá-lo para si mesmo. O ASP.NET Core codifica todas as saídas do lado do servidor de variáveis por padrão, reduzindo o risco de XSS. Se você substituir esse comportamento usando Html.Raw ou código personalizado com entrada não confiável, poderá aumentar o risco de XSS.
Não se preocupe com a vulnerabilidade CSRF se o token estiver armazenado no armazenamento local do navegador. O CSRF é uma preocupação quando o token é armazenado em um cookie. Para mais informações, consulte o problema do GitHub exemplo de código SPA adiciona dois cookies.
Vários aplicativos hospedados em um domínio
Os ambientes de hospedagem compartilhada são vulneráveis ao sequestro de sessão, ao CSRF de logon e a outros ataques.
Embora example1.contoso.net e example2.contoso.net sejam hosts diferentes, há uma relação de confiança implícita entre hosts no domínio *.contoso.net. Essa relação de confiança implícita permite que hosts potencialmente não confiáveis afetem os cookies uns dos outros (as políticas de mesma origem que regem as solicitações AJAX não se aplicam necessariamente a cookies de HTTP).
Ataques que exploram cookies confiáveis entre aplicativos hospedados no mesmo domínio podem ser evitados ao não compartilhar domínios. Quando cada aplicativo é hospedado em seu próprio domínio, não há nenhuma relação de confiança implícita cookie a ser explorada.
Antifalsificação no ASP.NET Core
Aviso
ASP.NET Core implementa antifalsificação por meio da Proteção de Dados do ASP.NET Core. A pilha de proteção de dados deve ser configurada para funcionar em um farm de servidores. Para obter mais informações, consulte Como configurar a proteção de dados.
O middleware antifalsificação é adicionado ao contêiner de Injeção de dependência quando uma das seguintes APIs é chamada em Program.cs:
O FormTagHelper injeta tokens antifalsificação em elementos de formulário HTML. A marcação a seguir em um arquivo Razor gera tokens antifalsificação automaticamente:
<form method="post">
<!-- ... -->
</form>
Da mesma forma, IHtmlHelper.BeginForm gera tokens antifalsificação por padrão se o método do formulário não for GET.
A geração automática de tokens antifalsificação para elementos de formulário HTML ocorre quando a marca <form> contém o atributo method="post" e alguma das seguintes alternativas sejam verdadeiras:
- O atributo de ação está vazio (
action=""). - O atributo de ação não foi fornecido (
<form method="post">).
A geração automática de tokens antifalsificação para elementos de formulário HTML pode ser desabilitada:
Desabilite explicitamente os tokens de antifalsificação com o atributo
asp-antiforgery.<form method="post" asp-antiforgery="false"> <!-- ... --> </form>O elemento formulário é recusado nos Auxiliares de Marca usando o símbolo ! recusar do Auxiliar de Marca:
<!form method="post"> <!-- ... --> </!form>Remova o
FormTagHelperda visualização. OFormTagHelperpode ser removido de uma visão adicionando a seguinte diretiva à visão Razor:@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
Observação
As páginas são automaticamente protegidas contra XSRF/CSRF. Para obter mais informações, consulte XSRF/CSRF e Razor Páginas.
A abordagem mais comum para se defender contra ataques CSRF é usar o Padrão de Token do Sincronizador (STP). O STP é usado quando o usuário solicita uma página com dados de formulário:
- O servidor envia um token associado à identidade do usuário atual para o cliente.
- O cliente envia de volta o token para o servidor para verificação.
- Se o servidor receber um token que não corresponda à identidade do usuário autenticado, a solicitação será rejeitada.
O token é exclusivo e imprevisível. O token também pode ser usado para garantir o sequenciamento adequado de uma série de solicitações (por exemplo, garantindo a sequência de solicitações de: página 1 > página 2 > página 3). Todos os formulários em ASP.NET Core modelos MVC e Páginas Razor geram tokens antifalsificação. O seguinte par de exemplos de modo de exibição gera tokens antifalsificação:
<form asp-action="Index" asp-controller="Home" method="post">
<!-- ... -->
</form>
@using (Html.BeginForm("Index", "Home"))
{
<!-- ... -->
}
Adicione explicitamente um token antifalsificação a um <form> elemento sem usar Auxiliares de Marca com o auxiliar HTML @Html.AntiForgeryToken :
<form asp-action="Index" asp-controller="Home" method="post">
@Html.AntiForgeryToken()
<!-- ... -->
</form>
Em cada um dos casos anteriores, o ASP.NET Core adiciona um campo de formulário oculto semelhante ao seguinte exemplo:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
O ASP.NET Core inclui três filtros para trabalhar com tokens antifalsificação:
Antifalsificação com AddControllers
Chamar AddControllersnão habilita tokens antifalsificação. AddControllersWithViews deve ser chamado para ter suporte interno a tokens antifalsificação.
Várias guias do navegador e o padrão de token do sincronizador
Com o Padrão de Token do Sincronizador, apenas a página carregada mais recentemente contém um token antifalsificação válido. O uso de várias guias pode ser problemático. Por exemplo, se um usuário abrir várias abas:
- Somente a guia carregada mais recentemente contém um token antifalsificação válido.
- As solicitações feitas a partir de guias previamente carregadas falham com um erro:
Antiforgery token validation failed. The antiforgery cookie token and request token do not match
Considere padrões de proteção CSRF alternativos se isso representar um problema.
Configurar antifalsificação com AntiforgeryOptions
Personalize AntiforgeryOptions no arquivo Program do aplicativo:
builder.Services.AddAntiforgery(options =>
{
// Set Cookie properties using CookieBuilder properties†.
options.FormFieldName = "AntiforgeryFieldname";
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
options.SuppressXFrameOptionsHeader = false;
});
Defina as propriedades cookie antifalsificação usando as propriedades da classe CookieBuilder, conforme mostrado na tabela a seguir.
| Opção | Descrição |
|---|---|
| Cookie | Determina as configurações usadas para criar os cookies antifalsificação. |
| FormFieldName | O nome do campo de formulário oculto usado pelo sistema antifalsificação para renderizar tokens antifalsificação em modos de exibição. |
| HeaderName | O nome do cabeçalho usado pelo sistema antifalsificação. Se null, o sistema considerará apenas os dados do formulário. |
| SuppressXFrameOptionsHeader | Especifica se a geração do X-Frame-Options cabeçalho deve ser suprimida. Por padrão, o cabeçalho é gerado com um valor de "SAMEORIGIN". Assume o padrão de false. |
Alguns navegadores não permitem que endereços inseguros definam cookies com a marcação 'secure' ou sobrescrevam cookies cuja marcação 'secure' foi configurada (para obter mais informações, consulte A modificação preterida de cookies 'seguros' de origens não seguras). Como a mistura dos pontos de extremidade seguros e inseguros é um cenário comum em aplicativos, o ASP.NET Core relaxa a restrição à política de segurança em alguns cookies, como a antifalsificação cookie, definindo o cookie do SecurePolicy como CookieSecurePolicy.None. Mesmo que roube uma antifalsificação cookie, um usuário mal-intencionado também deve roubar o token de antifalsificação normalmente enviado por meio de um campo de formulário (mais comum) ou um cabeçalho de solicitação à parte (menos comum) mais a autenticação cookie. Cookies relacionados à autenticação ou autorização usam uma política mais forte que CookieSecurePolicy.None.
Você também pode proteger a antifalsificação cookie em ambientes que não sejam Development usando SSL (Secure Sockets Layer), somente via HTTPS, com a seguinte configuração de propriedade AntiforgeryOptions.Cookie no arquivo Program do aplicativo:
if (!builder.Environment.IsDevelopment())
{
builder.Services.AddAntiforgery(o =>
{
o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
}
Para obter mais informações, consulte CookieAuthenticationOptions.
Gerar tokens antifalsificação com IAntiforgery
IAntiforgery fornece a API para configurar recursos antifalsificação.
IAntiforgery pode ser solicitado no Program.cs usando WebApplication.Services. O exemplo a seguir usa o middleware da página inicial do aplicativo para gerar um token antifalsificação e enviá-lo na resposta como um cookie:
app.UseRouting();
app.UseAuthorization();
var antiforgery = app.Services.GetRequiredService<IAntiforgery>();
app.Use((context, next) =>
{
var requestPath = context.Request.Path.Value;
if (string.Equals(requestPath, "/", StringComparison.OrdinalIgnoreCase)
|| string.Equals(requestPath, "/index.html", StringComparison.OrdinalIgnoreCase))
{
var tokenSet = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokenSet.RequestToken!,
new CookieOptions { HttpOnly = false });
}
return next(context);
});
O exemplo anterior define um cookie nomeado XSRF-TOKEN. O cliente pode ler esse cookie e fornecer seu valor como um cabeçalho anexado a solicitações AJAX. Por exemplo, o Angular inclui proteção XSRF interna que lê um cookie nomeado XSRF-TOKEN por padrão.
Exigir validação antifalsificação
O filtro de ação ValidateAntiForgeryToken pode ser aplicado a uma ação individual, a um controlador ou globalmente. As solicitações feitas às ações que têm esse filtro aplicado são bloqueadas, a menos que a solicitação inclua um token antifalsificação válido:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index()
{
// ...
return RedirectToAction();
}
O atributo ValidateAntiForgeryToken exige um token para solicitações para os métodos de ação que marca, incluindo solicitações HTTP GET. Se o atributo ValidateAntiForgeryToken for aplicado entre os controladores do aplicativo, ele poderá ser substituído pelo atributo IgnoreAntiforgeryToken.
Validar automaticamente tokens antifalsificação somente para métodos HTTP não seguros
Em vez de aplicar amplamente o atributo ValidateAntiForgeryToken e substituí-lo por atributos IgnoreAntiforgeryToken, o atributo AutoValidateAntiforgeryToken pode ser usado. Esse atributo funciona de forma idêntica ao atributo ValidateAntiForgeryToken, mas ele não requer tokens para solicitações feitas usando os seguintes métodos HTTP:
- GET
- HEAD
- OPÇÕES
- TRACE
É recomendável usar amplamente AutoValidateAntiforgeryToken para cenários que não são de API. Esse atributo garante que as ações POST sejam protegidas por padrão. A alternativa é ignorar, por padrão, os tokens antifalsificação, a menos que ValidateAntiForgeryToken seja aplicado a métodos de ação individuais. Nesse cenário, é mais provável que um método de ação POST seja deixado desprotegido por engano, deixando o aplicativo vulnerável a ataques CSRF. Todos os POSTs devem enviar o token antifalsificação.
As APIs não têm um mecanismo automático para enviar a partecookie que não é do token. A implementação provavelmente depende da implementação do código do cliente. Mostramos alguns exemplos abaixo:
Exemplo de nível de classe:
[AutoValidateAntiforgeryToken]
public class HomeController : Controller
Exemplo global:
builder.Services.AddControllersWithViews(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
Substituir atributos antifalsificação globais ou de controlador
O filtro IgnoreAntiforgeryToken é usado para eliminar a necessidade de um token antifalsificação para uma determinada ação (ou controlador). Quando aplicado, esse filtro substitui os filtros ValidateAntiForgeryToken e AutoValidateAntiforgeryToken especificados em um nível superior (globalmente ou em um controlador).
[IgnoreAntiforgeryToken]
public IActionResult IndexOverride()
{
// ...
return RedirectToAction();
}
Atualizar tokens após a autenticação
Os tokens devem ser atualizados depois que o usuário é autenticado redirecionando o usuário para um modo de exibição ou para a página de Páginas Razor.
JavaScript, AJAX e SPAs
Em aplicativos tradicionais baseados em HTML, tokens antifalsificação são passados para o servidor usando campos de formulário ocultos. Em SPAs e aplicativos modernos baseados em JavaScript, muitas solicitações são feitas programaticamente. Essas solicitações AJAX podem usar outras técnicas (como cabeçalhos de solicitação ou cookies) para enviar o token.
Se cookies forem usados para armazenar tokens de autenticação e autenticar solicitações de API no servidor, o CSRF é um problema em potencial. Se o armazenamento local for usado para armazenar o token, a vulnerabilidade CSRF poderá ser atenuada porque os valores do armazenamento local não são enviados automaticamente para o servidor a cada solicitação. Usar o armazenamento local para armazenar o token antifalsificação no cliente e enviar o token como um cabeçalho de solicitação é uma abordagem recomendada.
JavaScript
Usando JavaScript com modos de exibição, o token pode ser criado usando um serviço de dentro da exibição. Injete o serviço IAntiforgery na exibição e chame GetAndStoreTokens:
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery
@{
ViewData["Title"] = "JavaScript";
var requestToken = Antiforgery.GetAndStoreTokens(Context).RequestToken;
}
<input id="RequestVerificationToken" type="hidden" value="@requestToken" />
<button id="button" class="btn btn-primary">Submit with Token</button>
<div id="result" class="mt-2"></div>
@section Scripts {
<script>
document.addEventListener("DOMContentLoaded", () => {
const resultElement = document.getElementById("result");
document.getElementById("button").addEventListener("click", async () => {
const response = await fetch("@Url.Action("FetchEndpoint")", {
method: "POST",
headers: {
RequestVerificationToken:
document.getElementById("RequestVerificationToken").value
}
});
if (response.ok) {
resultElement.innerText = await response.text();
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
});
});
</script>
}
O exemplo anterior usa JavaScript para ler o valor do campo oculto para o cabeçalho POST do AJAX.
Essa abordagem elimina a necessidade de lidar diretamente com a configuração de cookies do servidor ou de lê-los a partir do cliente. No entanto, quando não for possível injetar o serviço IAntiforgery, use JavaScript para acessar tokens em cookies:
- Tokens de acesso em uma solicitação adicional para o servidor, normalmente
same-origin. - Utilize o conteúdo do cookie para criar um cabeçalho com o valor do token.
Supondo que o script envie o token em um cabeçalho de solicitação chamado X-XSRF-TOKEN, configure o serviço antifalsificação para procurar o cabeçalho X-XSRF-TOKEN:
builder.Services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
O exemplo a seguir adiciona um ponto de extremidade protegido que grava o token de solicitação em um JavaScript legível cookie:
app.UseAuthorization();
app.MapGet("antiforgery/token", (IAntiforgery forgeryService, HttpContext context) =>
{
var tokens = forgeryService.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken!,
new CookieOptions { HttpOnly = false });
return Results.Ok();
}).RequireAuthorization();
O exemplo a seguir usa JavaScript para fazer uma solicitação AJAX para obter o token e fazer outra solicitação com o cabeçalho apropriado:
var response = await fetch("/antiforgery/token", {
method: "GET",
headers: { "Authorization": authorizationToken }
});
if (response.ok) {
// https://developer.mozilla.org/docs/web/api/document/cookie
const xsrfToken = document.cookie
.split("; ")
.find(row => row.startsWith("XSRF-TOKEN="))
.split("=")[1];
response = await fetch("/JavaScript/FetchEndpoint", {
method: "POST",
headers: { "X-XSRF-TOKEN": xsrfToken, "Authorization": authorizationToken }
});
if (response.ok) {
resultElement.innerText = await response.text();
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
Observação
Quando o token antifalsificação é fornecido no cabeçalho da solicitação e no conteúdo do formulário, somente o token no cabeçalho é validado.
Antifalsificação com APIs Minimalistas
Minimal APIs não dão suporte ao uso dos filtros incluídos (ValidateAntiForgeryToken, AutoValidateAntiforgeryToken, IgnoreAntiforgeryToken), no entanto, IAntiforgery fornece as APIs necessárias para validar uma solicitação.
O exemplo a seguir cria um filtro que valida o token antifalsificação:
internal static class AntiForgeryExtensions
{
public static TBuilder ValidateAntiforgery<TBuilder>(this TBuilder builder) where TBuilder : IEndpointConventionBuilder
{
return builder.AddEndpointFilter(routeHandlerFilter: async (context, next) =>
{
try
{
var antiForgeryService = context.HttpContext.RequestServices.GetRequiredService<IAntiforgery>();
await antiForgeryService.ValidateRequestAsync(context.HttpContext);
}
catch (AntiforgeryValidationException)
{
return Results.BadRequest("Antiforgery token validation failed.");
}
return await next(context);
});
}
}
Em seguida, o filtro pode ser aplicado a um ponto de extremidade:
app.MapPost("api/upload", (IFormFile name) => Results.Accepted())
.RequireAuthorization()
.ValidateAntiforgery();
Autenticação do Windows e cookies antifalsificação
Ao utilizar a autenticação do Windows, os pontos de extremidade do aplicativo devem ser protegidos contra ataques CSRF da mesma maneira que se faz com cookies. O navegador envia implicitamente o contexto de autenticação para o servidor e os endpoints precisam ser protegidos contra ataques CSRF.
Estender a antifalsificação
O tipo IAntiforgeryAdditionalDataProvider permite que os desenvolvedores estendam o comportamento do sistema anti-CSRF ao arredondar dados adicionais em cada token. O método GetAdditionalData é chamado sempre que um token de campo é gerado e o valor retornado é inserido no token gerado. Um implementador pode retornar um timestamp, um nonce ou qualquer outro valor e, em seguida, chamar ValidateAdditionalData para validar esse dado quando o token for validado. O nome de usuário do cliente já está inserido nos tokens gerados, portanto, não é necessário incluir essas informações. Se um token incluir dados complementares, mas nenhum IAntiForgeryAdditionalDataProvider estiver configurado, os dados complementares não serão validados.
Recursos adicionais
A solicitação entre sites forjada (também conhecida como XSRF ou CSRF) é um ataque contra aplicativos Web hospedados, no qual um site mal-intencionado pode influenciar a interação entre um navegador cliente e um aplicativo Web que confia nesse navegador. Os ataques são possíveis porque os navegadores enviam automaticamente alguns tipos de tokens de autenticação com cada solicitação a um site. Essa forma de exploração também é conhecida como ataque de um clique ou sequestro de sessão, pois o ataque aproveita a sessão autenticada anteriormente pelo usuário.
Um exemplo de ataque CSRF:
Um usuário faz login no
www.good-banking-site.example.comusando a autenticação de formulários. O servidor autentica o usuário e emite uma resposta que inclui uma autenticação cookie. O site é vulnerável a ataques porque confia em qualquer solicitação recebida com uma autenticação cookieválida.O usuário visita um site mal-intencionado,
www.bad-crook-site.example.com.O site mal-intencionado,
www.bad-crook-site.example.com, contém um formulário HTML semelhante ao seguinte exemplo:<h1>Congratulations! You're a Winner!</h1> <form action="https://www.good-banking-site.example.com/api/account" method="post"> <input type="hidden" name="Transaction" value="withdraw" /> <input type="hidden" name="Amount" value="1000000" /> <input type="submit" value="Click to collect your prize!" /> </form>Observe que o formulário publica
actionno site vulnerável, não no site mal-intencionado. Essa é a parte "entre sites" do CSRF.O usuário seleciona o botão Enviar. O navegador faz a solicitação e inclui automaticamente a autenticação cookie para o domínio solicitado,
www.good-banking-site.example.com.A solicitação é executada no servidor
www.good-banking-site.example.comcom o contexto de autenticação do usuário e pode executar qualquer ação que um usuário autenticado tenha permissão para executar.
Além do cenário em que o usuário seleciona o botão para enviar o formulário, o site mal-intencionado pode:
- Executar um script que envia automaticamente o formulário.
- Enviar o envio do formulário como uma solicitação AJAX.
- Ocultar o formulário usando CSS.
Esses cenários alternativos não exigem nenhuma ação ou entrada do usuário além de visitar inicialmente o site mal-intencionado.
O uso de HTTPS não impede um ataque CSRF. O site malicioso pode enviar uma solicitação https://www.good-banking-site.example.com/ tão facilmente quanto uma solicitação insegura.
Alguns ataques visam pontos de extremidade que respondem a solicitações GET, nesse caso, uma marca de imagem pode ser usada para executar a ação. Essa forma de ataque é comum em sites de fórum que permitem imagens, mas bloqueiam JavaScript. Aplicativos que alteram o estado em solicitações GET, em que variáveis ou recursos são alterados, são vulneráveis a ataques mal-intencionados. Solicitações GET que alteram o estado são inseguras. Uma prática recomendada é nunca alterar o estado em uma solicitação GET.
Ataques CSRF são possíveis contra aplicativos Web que usam cookies para autenticação porque:
- Os navegadores armazenam cookies emitidos por um aplicativo Web.
- Os cookies armazenados incluem cookies de sessões de usuários autenticados.
- Os navegadores enviam todos os os cookies associados a um domínio para o aplicativo Web a cada solicitação, independentemente de como a solicitação para o aplicativo foi gerada no navegador.
Entretanto, os ataques CSRF não se limitam à exploração de cookies. Por exemplo, a autenticação Básica e Digest também são vulneráveis. Depois que um usuário entra com a autenticação Básica ou Digest, o navegador envia automaticamente as credenciais até que a sessão termine.
Nesse contexto, a sessão refere-se à sessão do lado do cliente durante a qual o usuário é autenticado. Não está relacionado às sessões no lado do servidor nem ao middleware de sessão do ASP.NET Core.
Os usuários podem se proteger contra vulnerabilidades CSRF ao tomar precauções:
- Saia dos aplicativos Web quando terminar de usá-los.
- Limpe os os cookies do navegador periodicamente.
No entanto, as vulnerabilidades CSRF são fundamentalmente um problema com o aplicativo Web, não com o usuário final.
Conceitos básicos sobre autenticação
A autenticação baseada em Cookie é uma forma popular de autenticação. Os sistemas de autenticação baseados em token estão crescendo em popularidade, especialmente para Aplicativos de Página Única (SPAs).
Autenticação baseada em Cookie
Quando um usuário se autentica usando seu nome de usuário e senha, ele recebe um token, contendo um tíquete de autenticação que pode ser usado para autenticação e autorização. O token é armazenado como um cookie que é enviado com cada solicitação que o cliente faz. A geração e a validação deste cookie são realizadas pelo middleware de autenticação cookie. O middleware serializa uma entidade de segurança de usuário em um criptografado cookie. Em solicitações subsequentes, o middleware valida o cookie, recria a entidade de segurança e atribui a entidade de segurança à propriedade HttpContext.User.
Autenticação baseada em token
Quando um usuário é autenticado, um token é emitido para ele (não um token antifalsificação). O token contém informações do usuário na forma de declarações ou um token de referência que aponta o aplicativo para o estado do usuário mantido no aplicativo. Quando um usuário tenta acessar um recurso que requer autenticação, o token é enviado para o aplicativo com um cabeçalho de autorização extra na forma de um token de portador. Essa abordagem torna o aplicativo sem estado. Em cada solicitação subsequente, o token é passado na solicitação de validação do lado do servidor. Esse token não é criptografado, ele é codificado. No servidor, o token é decodificado para acessar suas informações. Para enviar o token em solicitações subsequentes, armazene o token no armazenamento local do navegador. Não se preocupe com a vulnerabilidade CSRF se o token estiver armazenado no armazenamento local do navegador. O CSRF é uma preocupação quando o token é armazenado em um cookie. Para mais informações, consulte o problema do GitHub exemplo de código SPA adiciona dois cookies.
Vários aplicativos hospedados em um domínio
Os ambientes de hospedagem compartilhada são vulneráveis ao sequestro de sessão, ao CSRF de logon e a outros ataques.
Embora example1.contoso.net e example2.contoso.net sejam hosts diferentes, há uma relação de confiança implícita entre hosts no domínio *.contoso.net. Essa relação de confiança implícita permite que hosts potencialmente não confiáveis afetem os cookies uns dos outros (as políticas de mesma origem que regem as solicitações AJAX não se aplicam necessariamente a cookies de HTTP).
Ataques que exploram cookies confiáveis entre aplicativos hospedados no mesmo domínio podem ser evitados ao não compartilhar domínios. Quando cada aplicativo é hospedado em seu próprio domínio, não há nenhuma relação de confiança implícita cookie a ser explorada.
Antifalsificação no ASP.NET Core
Aviso
ASP.NET Core implementa antifalsificação por meio da Proteção de Dados do ASP.NET Core. A pilha de proteção de dados deve ser configurada para funcionar em um farm de servidores. Para obter mais informações, consulte Como configurar a proteção de dados.
O middleware antifalsificação é adicionado ao contêiner de Injeção de dependência quando uma das seguintes APIs é chamada em Program.cs:
O FormTagHelper injeta tokens antifalsificação em elementos de formulário HTML. A marcação a seguir em um arquivo Razor gera tokens antifalsificação automaticamente:
<form method="post">
<!-- ... -->
</form>
Da mesma forma, IHtmlHelper.BeginForm gera tokens antifalsificação por padrão se o método do formulário não for GET.
A geração automática de tokens antifalsificação para elementos de formulário HTML ocorre quando a marca <form> contém o atributo method="post" e alguma das seguintes alternativas sejam verdadeiras:
- O atributo de ação está vazio (
action=""). - O atributo de ação não foi fornecido (
<form method="post">).
A geração automática de tokens antifalsificação para elementos de formulário HTML pode ser desabilitada:
Desabilite explicitamente os tokens de antifalsificação com o atributo
asp-antiforgery.<form method="post" asp-antiforgery="false"> <!-- ... --> </form>O elemento formulário é recusado nos Auxiliares de Marca usando o símbolo ! recusar do Auxiliar de Marca:
<!form method="post"> <!-- ... --> </!form>Remova o
FormTagHelperda visualização. OFormTagHelperpode ser removido de uma visão adicionando a seguinte diretiva à visão Razor:@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
Observação
As páginas são automaticamente protegidas contra XSRF/CSRF. Para obter mais informações, consulte XSRF/CSRF e Razor Páginas.
A abordagem mais comum para se defender contra ataques CSRF é usar o Padrão de Token do Sincronizador (STP). O STP é usado quando o usuário solicita uma página com dados de formulário:
- O servidor envia um token associado à identidade do usuário atual para o cliente.
- O cliente envia de volta o token para o servidor para verificação.
- Se o servidor receber um token que não corresponda à identidade do usuário autenticado, a solicitação será rejeitada.
O token é exclusivo e imprevisível. O token também pode ser usado para garantir o sequenciamento adequado de uma série de solicitações (por exemplo, garantindo a sequência de solicitações de: página 1 > página 2 > página 3). Todos os formulários em ASP.NET Core modelos MVC e Páginas Razor geram tokens antifalsificação. O seguinte par de exemplos de modo de exibição gera tokens antifalsificação:
<form asp-action="Index" asp-controller="Home" method="post">
<!-- ... -->
</form>
@using (Html.BeginForm("Index", "Home"))
{
<!-- ... -->
}
Adicione explicitamente um token antifalsificação a um <form> elemento sem usar Auxiliares de Marca com o auxiliar HTML @Html.AntiForgeryToken :
<form asp-action="Index" asp-controller="Home" method="post">
@Html.AntiForgeryToken()
<!-- ... -->
</form>
Em cada um dos casos anteriores, o ASP.NET Core adiciona um campo de formulário oculto semelhante ao seguinte exemplo:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
O ASP.NET Core inclui três filtros para trabalhar com tokens antifalsificação:
Antifalsificação com AddControllers
Chamar AddControllersnão habilita tokens antifalsificação. AddControllersWithViews deve ser chamado para ter suporte interno a tokens antifalsificação.
Várias guias do navegador e o padrão de token do sincronizador
Com o Padrão de Token do Sincronizador, apenas a página carregada mais recentemente contém um token antifalsificação válido. O uso de várias guias pode ser problemático. Por exemplo, se um usuário abrir várias abas:
- Somente a guia carregada mais recentemente contém um token antifalsificação válido.
- As solicitações feitas a partir de guias previamente carregadas falham com um erro:
Antiforgery token validation failed. The antiforgery cookie token and request token do not match
Considere padrões de proteção CSRF alternativos se isso representar um problema.
Configurar antifalsificação com AntiforgeryOptions
Personalize AntiforgeryOptions no arquivo Program do aplicativo:
builder.Services.AddAntiforgery(options =>
{
// Set Cookie properties using CookieBuilder properties†.
options.FormFieldName = "AntiforgeryFieldname";
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
options.SuppressXFrameOptionsHeader = false;
});
Defina as propriedades cookie antifalsificação usando as propriedades da classe CookieBuilder, conforme mostrado na tabela a seguir.
| Opção | Descrição |
|---|---|
| Cookie | Determina as configurações usadas para criar os cookies antifalsificação. |
| FormFieldName | O nome do campo de formulário oculto usado pelo sistema antifalsificação para renderizar tokens antifalsificação em modos de exibição. |
| HeaderName | O nome do cabeçalho usado pelo sistema antifalsificação. Se null, o sistema considerará apenas os dados do formulário. |
| SuppressXFrameOptionsHeader | Especifica se a geração do X-Frame-Options cabeçalho deve ser suprimida. Por padrão, o cabeçalho é gerado com um valor de "SAMEORIGIN". Assume o padrão de false. |
Alguns navegadores não permitem que endereços inseguros definam cookies com a marcação 'secure' ou sobrescrevam cookies cuja marcação 'secure' foi configurada (para obter mais informações, consulte A modificação preterida de cookies 'seguros' de origens não seguras). Como a mistura dos pontos de extremidade seguros e inseguros é um cenário comum em aplicativos, o ASP.NET Core relaxa a restrição à política de segurança em alguns cookies, como a antifalsificação cookie, definindo o cookie do SecurePolicy como CookieSecurePolicy.None. Mesmo que roube uma antifalsificação cookie, um usuário mal-intencionado também deve roubar o token de antifalsificação normalmente enviado por meio de um campo de formulário (mais comum) ou um cabeçalho de solicitação à parte (menos comum) mais a autenticação cookie. Cookies relacionados à autenticação ou autorização usam uma política mais forte que CookieSecurePolicy.None.
Você também pode proteger a antifalsificação cookie em ambientes que não sejam Development usando SSL (Secure Sockets Layer), somente via HTTPS, com a seguinte configuração de propriedade AntiforgeryOptions.Cookie no arquivo Program do aplicativo:
if (!builder.Environment.IsDevelopment())
{
builder.Services.AddAntiforgery(o =>
{
o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
}
Para obter mais informações, consulte CookieAuthenticationOptions.
Gerar tokens antifalsificação com IAntiforgery
IAntiforgery fornece a API para configurar recursos antifalsificação.
IAntiforgery pode ser solicitado no Program.cs usando WebApplication.Services. O exemplo a seguir usa o middleware da página inicial do aplicativo para gerar um token antifalsificação e enviá-lo na resposta como um cookie:
app.UseRouting();
app.UseAuthorization();
var antiforgery = app.Services.GetRequiredService<IAntiforgery>();
app.Use((context, next) =>
{
var requestPath = context.Request.Path.Value;
if (string.Equals(requestPath, "/", StringComparison.OrdinalIgnoreCase)
|| string.Equals(requestPath, "/index.html", StringComparison.OrdinalIgnoreCase))
{
var tokenSet = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokenSet.RequestToken!,
new CookieOptions { HttpOnly = false });
}
return next(context);
});
O exemplo anterior define um cookie nomeado XSRF-TOKEN. O cliente pode ler esse cookie e fornecer seu valor como um cabeçalho anexado a solicitações AJAX. Por exemplo, o Angular inclui proteção XSRF interna que lê um cookie nomeado XSRF-TOKEN por padrão.
Exigir validação antifalsificação
O filtro de ação ValidateAntiForgeryToken pode ser aplicado a uma ação individual, a um controlador ou globalmente. As solicitações feitas às ações que têm esse filtro aplicado são bloqueadas, a menos que a solicitação inclua um token antifalsificação válido:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index()
{
// ...
return RedirectToAction();
}
O atributo ValidateAntiForgeryToken exige um token para solicitações para os métodos de ação que marca, incluindo solicitações HTTP GET. Se o atributo ValidateAntiForgeryToken for aplicado entre os controladores do aplicativo, ele poderá ser substituído pelo atributo IgnoreAntiforgeryToken.
Validar automaticamente tokens antifalsificação somente para métodos HTTP não seguros
Em vez de aplicar amplamente o atributo ValidateAntiForgeryToken e substituí-lo por atributos IgnoreAntiforgeryToken, o atributo AutoValidateAntiforgeryToken pode ser usado. Esse atributo funciona de forma idêntica ao atributo ValidateAntiForgeryToken, mas ele não requer tokens para solicitações feitas usando os seguintes métodos HTTP:
- GET
- HEAD
- OPÇÕES
- TRACE
É recomendável usar amplamente AutoValidateAntiforgeryToken para cenários que não são de API. Esse atributo garante que as ações POST sejam protegidas por padrão. A alternativa é ignorar, por padrão, os tokens antifalsificação, a menos que ValidateAntiForgeryToken seja aplicado a métodos de ação individuais. Nesse cenário, é mais provável que um método de ação POST seja deixado desprotegido por engano, deixando o aplicativo vulnerável a ataques CSRF. Todos os POSTs devem enviar o token antifalsificação.
As APIs não têm um mecanismo automático para enviar a partecookie que não é do token. A implementação provavelmente depende da implementação do código do cliente. Mostramos alguns exemplos abaixo:
Exemplo de nível de classe:
[AutoValidateAntiforgeryToken]
public class HomeController : Controller
Exemplo global:
builder.Services.AddControllersWithViews(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
Substituir atributos antifalsificação globais ou de controlador
O filtro IgnoreAntiforgeryToken é usado para eliminar a necessidade de um token antifalsificação para uma determinada ação (ou controlador). Quando aplicado, esse filtro substitui os filtros ValidateAntiForgeryToken e AutoValidateAntiforgeryToken especificados em um nível superior (globalmente ou em um controlador).
[IgnoreAntiforgeryToken]
public IActionResult IndexOverride()
{
// ...
return RedirectToAction();
}
Atualizar tokens após a autenticação
Os tokens devem ser atualizados depois que o usuário é autenticado redirecionando o usuário para um modo de exibição ou para a página de Páginas Razor.
JavaScript, AJAX e SPAs
Em aplicativos tradicionais baseados em HTML, tokens antifalsificação são passados para o servidor usando campos de formulário ocultos. Em SPAs e aplicativos modernos baseados em JavaScript, muitas solicitações são feitas programaticamente. Essas solicitações AJAX podem usar outras técnicas (como cabeçalhos de solicitação ou cookies) para enviar o token.
Se cookies forem usados para armazenar tokens de autenticação e autenticar solicitações de API no servidor, o CSRF é um problema em potencial. Se o armazenamento local for usado para armazenar o token, a vulnerabilidade CSRF poderá ser atenuada porque os valores do armazenamento local não são enviados automaticamente para o servidor a cada solicitação. Usar o armazenamento local para armazenar o token antifalsificação no cliente e enviar o token como um cabeçalho de solicitação é uma abordagem recomendada.
JavaScript
Usando JavaScript com modos de exibição, o token pode ser criado usando um serviço de dentro da exibição. Injete o serviço IAntiforgery na exibição e chame GetAndStoreTokens:
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery
@{
ViewData["Title"] = "JavaScript";
var requestToken = Antiforgery.GetAndStoreTokens(Context).RequestToken;
}
<input id="RequestVerificationToken" type="hidden" value="@requestToken" />
<button id="button" class="btn btn-primary">Submit with Token</button>
<div id="result" class="mt-2"></div>
@section Scripts {
<script>
document.addEventListener("DOMContentLoaded", () => {
const resultElement = document.getElementById("result");
document.getElementById("button").addEventListener("click", async () => {
const response = await fetch("@Url.Action("FetchEndpoint")", {
method: "POST",
headers: {
RequestVerificationToken:
document.getElementById("RequestVerificationToken").value
}
});
if (response.ok) {
resultElement.innerText = await response.text();
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
});
});
</script>
}
O exemplo anterior usa JavaScript para ler o valor do campo oculto para o cabeçalho POST do AJAX.
Essa abordagem elimina a necessidade de lidar diretamente com a configuração de cookies do servidor ou de lê-los a partir do cliente. No entanto, quando não for possível injetar o serviço IAntiforgery, o JavaScript também poderá acessar o token em cookies, obtido de uma solicitação adicional para o servidor (geralmente same-origin), e usar o conteúdo do cookie para criar um cabeçalho com o valor do token.
Supondo que o script envie o token em um cabeçalho de solicitação chamado X-XSRF-TOKEN, configure o serviço antifalsificação para procurar o cabeçalho X-XSRF-TOKEN:
builder.Services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
O exemplo a seguir adiciona um ponto de extremidade protegido que grava o token de solicitação em um cookie legível pelo JavaScript:
app.UseAuthorization();
app.MapGet("antiforgery/token", (IAntiforgery forgeryService, HttpContext context) =>
{
var tokens = forgeryService.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken!,
new CookieOptions { HttpOnly = false });
return Results.Ok();
}).RequireAuthorization();
O exemplo a seguir usa JavaScript para fazer uma solicitação AJAX para obter o token e fazer outra solicitação com o cabeçalho apropriado:
var response = await fetch("/antiforgery/token", {
method: "GET",
headers: { "Authorization": authorizationToken }
});
if (response.ok) {
// https://developer.mozilla.org/docs/web/api/document/cookie
const xsrfToken = document.cookie
.split("; ")
.find(row => row.startsWith("XSRF-TOKEN="))
.split("=")[1];
response = await fetch("/JavaScript/FetchEndpoint", {
method: "POST",
headers: { "X-XSRF-TOKEN": xsrfToken, "Authorization": authorizationToken }
});
if (response.ok) {
resultElement.innerText = await response.text();
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
} else {
resultElement.innerText = `Request Failed: ${response.status}`
}
Autenticação do Windows e cookies antifalsificação
Ao utilizar a autenticação do Windows, os pontos de extremidade do aplicativo devem ser protegidos contra ataques CSRF da mesma maneira que se faz com cookies. O navegador envia implicitamente o contexto de autenticação para o servidor e, portanto, os endpoints precisam ser protegidos contra ataques CSRF.
Estender a antifalsificação
O tipo IAntiforgeryAdditionalDataProvider permite que os desenvolvedores estendam o comportamento do sistema anti-CSRF ao arredondar dados adicionais em cada token. O método GetAdditionalData é chamado sempre que um token de campo é gerado e o valor retornado é inserido no token gerado. Um implementador pode retornar um timestamp, um nonce ou qualquer outro valor e, em seguida, chamar ValidateAdditionalData para validar esse dado quando o token for validado. O nome de usuário do cliente já está inserido nos tokens gerados, portanto, não é necessário incluir essas informações. Se um token incluir dados complementares, mas nenhum IAntiForgeryAdditionalDataProvider estiver configurado, os dados complementares não serão validados.
Recursos adicionais
A solicitação entre sites forjada (também conhecida como XSRF ou CSRF) é um ataque contra aplicativos Web hospedados, no qual um site mal-intencionado pode influenciar a interação entre um navegador cliente e um aplicativo Web que confia nesse navegador. Os ataques são possíveis porque os navegadores enviam automaticamente alguns tipos de tokens de autenticação com cada solicitação a um site. Essa forma de exploração também é conhecida como ataque de um clique ou sequestro de sessão, pois o ataque aproveita a sessão autenticada anteriormente pelo usuário.
Um exemplo de ataque CSRF:
Um usuário faz login no
www.good-banking-site.example.comusando a autenticação de formulários. O servidor autentica o usuário e emite uma resposta que inclui uma autenticação cookie. O site é vulnerável a ataques porque confia em qualquer solicitação recebida com uma autenticação cookieválida.O usuário visita um site mal-intencionado,
www.bad-crook-site.example.com.O site mal-intencionado,
www.bad-crook-site.example.com, contém um formulário HTML semelhante ao seguinte exemplo:<h1>Congratulations! You're a Winner!</h1> <form action="https://www.good-banking-site.example.com/api/account" method="post"> <input type="hidden" name="Transaction" value="withdraw" /> <input type="hidden" name="Amount" value="1000000" /> <input type="submit" value="Click to collect your prize!" /> </form>Observe que o formulário publica
actionno site vulnerável, não no site mal-intencionado. Essa é a parte "entre sites" do CSRF.O usuário seleciona o botão Enviar. O navegador faz a solicitação e inclui automaticamente a autenticação cookie para o domínio solicitado,
www.good-banking-site.example.com.A solicitação é executada no servidor
www.good-banking-site.example.comcom o contexto de autenticação do usuário e pode executar qualquer ação que um usuário autenticado tenha permissão para executar.
Além do cenário em que o usuário seleciona o botão para enviar o formulário, o site mal-intencionado pode:
- Executar um script que envia automaticamente o formulário.
- Enviar o envio do formulário como uma solicitação AJAX.
- Ocultar o formulário usando CSS.
Esses cenários alternativos não exigem nenhuma ação ou entrada do usuário além de visitar inicialmente o site mal-intencionado.
O uso de HTTPS não impede um ataque CSRF. O site malicioso pode enviar uma solicitação https://www.good-banking-site.example.com/ tão facilmente quanto uma solicitação insegura.
Alguns ataques visam pontos de extremidade que respondem a solicitações GET, nesse caso, uma marca de imagem pode ser usada para executar a ação. Essa forma de ataque é comum em sites de fórum que permitem imagens, mas bloqueiam JavaScript. Aplicativos que alteram o estado em solicitações GET, em que variáveis ou recursos são alterados, são vulneráveis a ataques mal-intencionados. Solicitações GET que alteram o estado são inseguras. Uma prática recomendada é nunca alterar o estado em uma solicitação GET.
Ataques CSRF são possíveis contra aplicativos Web que usam cookies para autenticação porque:
- Os navegadores armazenam cookies emitidos por um aplicativo Web.
- Os cookies armazenados incluem cookies de sessões de usuários autenticados.
- Os navegadores enviam todos os os cookies associados a um domínio para o aplicativo Web a cada solicitação, independentemente de como a solicitação para o aplicativo foi gerada no navegador.
Entretanto, os ataques CSRF não se limitam à exploração de cookies. Por exemplo, a autenticação Básica e Digest também são vulneráveis. Depois que um usuário entra com a autenticação Básica ou Digest, o navegador envia automaticamente as credenciais até que a sessão termine.
Nesse contexto, a sessão refere-se à sessão do lado do cliente durante a qual o usuário é autenticado. Não está relacionado às sessões no lado do servidor nem ao middleware de sessão do ASP.NET Core.
Os usuários podem se proteger contra vulnerabilidades CSRF ao tomar precauções:
- Saia dos aplicativos Web quando terminar de usá-los.
- Limpe os os cookies do navegador periodicamente.
No entanto, as vulnerabilidades CSRF são fundamentalmente um problema com o aplicativo Web, não com o usuário final.
Conceitos básicos sobre autenticação
A autenticação baseada em Cookie é uma forma popular de autenticação. Os sistemas de autenticação baseados em token estão crescendo em popularidade, especialmente para Aplicativos de Página Única (SPAs).
Autenticação baseada em Cookie
Quando um usuário se autentica usando seu nome de usuário e senha, ele recebe um token, contendo um tíquete de autenticação que pode ser usado para autenticação e autorização. O token é armazenado como um cookie que é enviado com cada solicitação que o cliente faz. A geração e a validação deste cookie são realizadas pelo cookie middleware de autenticação. O middleware serializa uma entidade de segurança de usuário em um criptografado cookie. Em solicitações subsequentes, o middleware valida o cookie, recria a entidade de segurança e atribui a entidade de segurança à propriedade HttpContext.User.
Autenticação baseada em token
Quando um usuário é autenticado, um token é emitido para ele (não um token antifalsificação). O token contém informações do usuário na forma de declarações ou um token de referência que aponta o aplicativo para o estado do usuário mantido no aplicativo. Quando um usuário tenta acessar um recurso que requer autenticação, o token é enviado para o aplicativo com um cabeçalho de autorização extra na forma de um token de portador. Essa abordagem torna o aplicativo sem estado. Em cada solicitação subsequente, o token é passado na solicitação de validação do lado do servidor. Esse token não é criptografado, ele é codificado. No servidor, o token é decodificado para acessar suas informações. Para enviar o token em solicitações subsequentes, armazene o token no armazenamento local do navegador. Não se preocupe com a vulnerabilidade CSRF se o token estiver armazenado no armazenamento local do navegador. O CSRF é uma preocupação quando o token é armazenado em um cookie. Para mais informações, consulte o problema do GitHub exemplo de código SPA adiciona dois cookies.
Vários aplicativos hospedados em um domínio
Os ambientes de hospedagem compartilhada são vulneráveis ao sequestro de sessão, ao CSRF de logon e a outros ataques.
Embora example1.contoso.net e example2.contoso.net sejam hosts diferentes, há uma relação de confiança implícita entre hosts no domínio *.contoso.net. Essa relação de confiança implícita permite que hosts potencialmente não confiáveis afetem os cookies uns dos outros (as políticas de mesma origem que regem as solicitações AJAX não se aplicam necessariamente a cookies de HTTP).
Ataques que exploram cookies confiáveis entre aplicativos hospedados no mesmo domínio podem ser evitados ao não compartilhar domínios. Quando cada aplicativo é hospedado em seu próprio domínio, não há nenhuma relação de confiança implícita cookie a ser explorada.
Configuração antifalsificação do ASP.NET Core
Aviso
ASP.NET Core implementa antifalsificação por meio da Proteção de Dados do ASP.NET Core. A pilha de proteção de dados deve ser configurada para funcionar em um farm de servidores. Para obter mais informações, consulte Como configurar a proteção de dados.
O middleware antifalsificação é adicionado ao contêiner de Injeção de dependência quando uma das seguintes APIs é chamada em Startup.ConfigureServices:
No ASP.NET Core 2.0 ou posterior, o FormTagHelperinjeta tokens antifalsificação em elementos de formulário HTML. A marcação a seguir em um arquivo Razor gera tokens antifalsificação automaticamente:
<form method="post">
...
</form>
Da mesma forma, IHtmlHelper.BeginForm gera tokens antifalsificação por padrão se o método do formulário não for GET.
A geração automática de tokens antifalsificação para elementos de formulário HTML ocorre quando a marca <form> contém o atributo method="post" e alguma das seguintes alternativas sejam verdadeiras:
- O atributo de ação está vazio (
action=""). - O atributo de ação não foi fornecido (
<form method="post">).
A geração automática de tokens antifalsificação para elementos de formulário HTML pode ser desabilitada:
Desabilite explicitamente os tokens de antifalsificação com o atributo
asp-antiforgery.<form method="post" asp-antiforgery="false"> ... </form>O elemento formulário é recusado nos Auxiliares de Marca usando o símbolo ! recusar do Auxiliar de Marca:
<!form method="post"> ... </!form>Remova o
FormTagHelperda visualização. OFormTagHelperpode ser removido de uma visão adicionando a seguinte diretiva à visão Razor:@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
Observação
As páginas são automaticamente protegidas contra XSRF/CSRF. Para obter mais informações, consulte XSRF/CSRF e Razor Páginas.
A abordagem mais comum para se defender contra ataques CSRF é usar o Padrão de Token do Sincronizador (STP). O STP é usado quando o usuário solicita uma página com dados de formulário:
- O servidor envia um token associado à identidade do usuário atual para o cliente.
- O cliente envia de volta o token para o servidor para verificação.
- Se o servidor receber um token que não corresponda à identidade do usuário autenticado, a solicitação será rejeitada.
O token é exclusivo e imprevisível. O token também pode ser usado para garantir o sequenciamento adequado de uma série de solicitações (por exemplo, garantindo a sequência de solicitações de: página 1 > página 2 > página 3). Todos os formulários em ASP.NET Core modelos MVC e Páginas Razor geram tokens antifalsificação. O seguinte par de exemplos de modo de exibição gera tokens antifalsificação:
<form asp-controller="Todo" asp-action="Create" method="post">
...
</form>
@using (Html.BeginForm("Create", "Todo"))
{
...
}
Adicione explicitamente um token antifalsificação a um <form> elemento sem usar Auxiliares de Marca com o auxiliar HTML @Html.AntiForgeryToken :
<form action="/" method="post">
@Html.AntiForgeryToken()
</form>
Em cada um dos casos anteriores, o ASP.NET Core adiciona um campo de formulário oculto semelhante ao seguinte exemplo:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
O ASP.NET Core inclui três filtros para trabalhar com tokens antifalsificação:
Opções de antifalsificação
Personalize AntiforgeryOptions no Startup.ConfigureServices:
services.AddAntiforgery(options =>
{
options.FormFieldName = "AntiforgeryFieldname";
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
options.SuppressXFrameOptionsHeader = false;
});
Defina as propriedades cookie antifalsificação usando as propriedades da classe CookieBuilder, conforme mostrado na tabela a seguir.
| Opção | Descrição |
|---|---|
| Cookie | Determina as configurações usadas para criar os cookies antifalsificação. |
| FormFieldName | O nome do campo de formulário oculto usado pelo sistema antifalsificação para renderizar tokens antifalsificação em modos de exibição. |
| HeaderName | O nome do cabeçalho usado pelo sistema antifalsificação. Se null, o sistema considerará apenas os dados do formulário. |
| SuppressXFrameOptionsHeader | Especifica se a geração do X-Frame-Options cabeçalho deve ser suprimida. Por padrão, o cabeçalho é gerado com um valor de "SAMEORIGIN". Assume o padrão de false. |
Alguns navegadores não permitem que endereços inseguros definam cookies com a marcação 'secure' ou sobrescrevam cookies cuja marcação 'secure' foi configurada (para obter mais informações, consulte A modificação preterida de cookies 'seguros' de origens não seguras). Como a mistura dos pontos de extremidade seguros e inseguros é um cenário comum em aplicativos, o ASP.NET Core relaxa a restrição à política de segurança em alguns cookies, como a antifalsificação cookie, definindo o cookie do SecurePolicy como CookieSecurePolicy.None. Mesmo que roube uma antifalsificação cookie, um usuário mal-intencionado também deve roubar o token de antifalsificação normalmente enviado por meio de um campo de formulário (mais comum) ou um cabeçalho de solicitação à parte (menos comum) mais a autenticação cookie. Cookies relacionados à autenticação ou autorização usam uma política mais forte que CookieSecurePolicy.None.
Você também pode proteger a antifalsificação cookie em ambientes que não sejam Development usando SSL (Secure Sockets Layer), somente via HTTPS, com a seguinte configuração de propriedade AntiforgeryOptions.Cookie na classe Startup do aplicativo:
public class Startup
{
public Startup(IConfiguration configuration, IHostEnvironment environment)
{
Configuration = configuration;
Environment = environment;
}
public IConfiguration Configuration { get; }
public IHostEnvironment Environment { get; }
public void ConfigureServices(IServiceCollection services)
{
// Other services are registered here
if (!Environment.IsDevelopment())
{
services.AddAntiforgery(o =>
{
o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
}
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Request processing pipeline
}
}
Para obter mais informações, consulte CookieAuthenticationOptions.
Configurar recursos antifalsificação com o IAntiforgery
IAntiforgery fornece a API para configurar recursos antifalsificação. O IAntiforgery pode ser solicitado no método Configure da classe Startup .
No exemplo a seguir:
- O exemplo a seguir usa middleware da home page do aplicativo para gerar um token antifalsificação e enviá-lo na resposta como um cookie.
- O token de solicitação é enviado como um cookie legível por JavaScript com a convenção de nomenclatura do Angular padrão descrita na seção AngularJS.
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
app.Use(next => context =>
{
string path = context.Request.Path.Value;
if (string.Equals(path, "/", StringComparison.OrdinalIgnoreCase) ||
string.Equals(path, "/index.html", StringComparison.OrdinalIgnoreCase))
{
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
new CookieOptions() { HttpOnly = false });
}
return next(context);
});
}
Exigir validação antifalsificação
O filtro de ação ValidateAntiForgeryToken pode ser aplicado a uma ação individual, a um controlador ou globalmente. As solicitações feitas às ações que têm esse filtro aplicado são bloqueadas, a menos que a solicitação inclua um token antifalsificação válido.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> RemoveLogin(RemoveLoginViewModel account)
{
ManageMessageId? message = ManageMessageId.Error;
var user = await GetCurrentUserAsync();
if (user != null)
{
var result =
await _userManager.RemoveLoginAsync(
user, account.LoginProvider, account.ProviderKey);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
message = ManageMessageId.RemoveLoginSuccess;
}
}
return RedirectToAction(nameof(ManageLogins), new { Message = message });
}
O atributo ValidateAntiForgeryToken exige um token para solicitações para os métodos de ação que marca, incluindo solicitações HTTP GET. Se o atributo ValidateAntiForgeryToken for aplicado entre os controladores do aplicativo, ele poderá ser substituído pelo atributo IgnoreAntiforgeryToken.
Observação
O ASP.NET Core não é compatível com a adição automática de tokens antifalsificação a solicitações GET.
Validar automaticamente tokens antifalsificação somente para métodos HTTP não seguros
Os aplicativos ASP.NET Core não geram tokens antifalsificação para métodos HTTP seguros (GET, HEAD, OPTIONS e TRACE). Em vez de aplicar amplamente o atributo ValidateAntiForgeryToken e substituí-lo por atributos IgnoreAntiforgeryToken, o atributo AutoValidateAntiforgeryToken pode ser usado. Esse atributo funciona de forma idêntica ao atributo ValidateAntiForgeryToken, mas ele não requer tokens para solicitações feitas usando os seguintes métodos HTTP:
- GET
- HEAD
- OPÇÕES
- TRACE
É recomendável usar amplamente AutoValidateAntiforgeryToken para cenários que não são de API. Esse atributo garante que as ações POST sejam protegidas por padrão. A alternativa é ignorar, por padrão, os tokens antifalsificação, a menos que ValidateAntiForgeryToken seja aplicado a métodos de ação individuais. Nesse cenário, é mais provável que um método de ação POST seja deixado desprotegido por engano, deixando o aplicativo vulnerável a ataques CSRF. Todos os POSTs devem enviar o token antifalsificação.
As APIs não têm um mecanismo automático para enviar a partecookie que não é do token. A implementação provavelmente depende da implementação do código do cliente. Mostramos alguns exemplos abaixo:
Exemplo de nível de classe:
[Authorize]
[AutoValidateAntiforgeryToken]
public class ManageController : Controller
{
Exemplo global:
services.AddControllersWithViews(options =>
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()));
Substituir atributos antifalsificação globais ou de controlador
O filtro IgnoreAntiforgeryToken é usado para eliminar a necessidade de um token antifalsificação para uma determinada ação (ou controlador). Quando aplicado, esse filtro substitui os filtros ValidateAntiForgeryToken e AutoValidateAntiforgeryToken especificados em um nível superior (globalmente ou em um controlador).
[Authorize]
[AutoValidateAntiforgeryToken]
public class ManageController : Controller
{
[HttpPost]
[IgnoreAntiforgeryToken]
public async Task<IActionResult> DoSomethingSafe(SomeViewModel model)
{
// no antiforgery token required
}
}
Atualizar tokens após a autenticação
Os tokens devem ser atualizados depois que o usuário é autenticado redirecionando o usuário para um modo de exibição ou para a página de Páginas Razor.
JavaScript, AJAX e SPAs
Em aplicativos tradicionais baseados em HTML, tokens antifalsificação são passados para o servidor usando campos de formulário ocultos. Em SPAs e aplicativos modernos baseados em JavaScript, muitas solicitações são feitas programaticamente. Essas solicitações AJAX podem usar outras técnicas (como cabeçalhos de solicitação ou cookies) para enviar o token.
Se cookies forem usados para armazenar tokens de autenticação e autenticar solicitações de API no servidor, o CSRF é um problema em potencial. Se o armazenamento local for usado para armazenar o token, a vulnerabilidade CSRF poderá ser atenuada porque os valores do armazenamento local não são enviados automaticamente para o servidor a cada solicitação. Usar o armazenamento local para armazenar o token antifalsificação no cliente e enviar o token como um cabeçalho de solicitação é uma abordagem recomendada.
JavaScript
Usando JavaScript com modos de exibição, o token pode ser criado usando um serviço de dentro da exibição. Injete o serviço IAntiforgery na exibição e chame GetAndStoreTokens:
@{
ViewData["Title"] = "AJAX Demo";
}
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions{
public string GetAntiXsrfRequestToken()
{
return Xsrf.GetAndStoreTokens(Context).RequestToken;
}
}
<input type="hidden" id="RequestVerificationToken"
name="RequestVerificationToken" value="@GetAntiXsrfRequestToken()">
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>
<div class="row">
<p><input type="button" id="antiforgery" value="Antiforgery"></p>
<script>
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == XMLHttpRequest.DONE) {
if (xhttp.status == 200) {
alert(xhttp.responseText);
} else {
alert('There was an error processing the AJAX request.');
}
}
};
document.addEventListener('DOMContentLoaded', function() {
document.getElementById("antiforgery").onclick = function () {
xhttp.open('POST', '@Url.Action("Antiforgery", "Home")', true);
xhttp.setRequestHeader("RequestVerificationToken",
document.getElementById('RequestVerificationToken').value);
xhttp.send();
}
});
</script>
</div>
Essa abordagem elimina a necessidade de lidar diretamente com a configuração de cookies do servidor ou de lê-los a partir do cliente.
O exemplo anterior usa JavaScript para ler o valor do campo oculto para o cabeçalho POST do AJAX.
O JavaScript também pode acessar tokens em cookies e usar os conteúdos do cookie para criar um cabeçalho com o valor do token.
context.Response.Cookies.Append("CSRF-TOKEN", tokens.RequestToken,
new Microsoft.AspNetCore.Http.CookieOptions { HttpOnly = false });
Supondo que o script envie o token em um cabeçalho de solicitação chamado X-CSRF-TOKEN, configure o serviço antifalsificação para procurar o cabeçalho X-CSRF-TOKEN:
services.AddAntiforgery(options => options.HeaderName = "X-CSRF-TOKEN");
O exemplo a seguir usa JavaScript para fazer uma solicitação AJAX com o cabeçalho apropriado:
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) === ' ') {
c = c.substring(1);
}
if (c.indexOf(name) === 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
var csrfToken = getCookie("CSRF-TOKEN");
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (xhttp.readyState === XMLHttpRequest.DONE) {
if (xhttp.status === 204) {
alert('Todo item is created successfully.');
} else {
alert('There was an error processing the AJAX request.');
}
}
};
xhttp.open('POST', '/api/items', true);
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.setRequestHeader("X-CSRF-TOKEN", csrfToken);
xhttp.send(JSON.stringify({ "name": "Learn C#" }));
AngularJS
O AngularJS usa uma convenção para lidar com CSRF. Se o servidor enviar um cookie com o nome XSRF-TOKEN, o serviço $http do AngularJS adicionará o valor cookie a um cabeçalho quando enviar uma solicitação ao servidor. Esse processo é automático. O cliente não precisa definir o cabeçalho explicitamente. O nome do cabeçalho é X-XSRF-TOKEN. O servidor deve detectar esse cabeçalho e validar seu conteúdo.
Para que o ASP.NET Core API funcione com essa convenção na inicialização do aplicativo:
- Configure seu aplicativo para fornecer um token em um cookie chamado
XSRF-TOKEN. - Configure o serviço antifalsificação para procurar um cabeçalho chamado
X-XSRF-TOKEN, que é o nome de cabeçalho padrão do Angular para enviar o token XSRF.
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
app.Use(next => context =>
{
string path = context.Request.Path.Value;
if (
string.Equals(path, "/", StringComparison.OrdinalIgnoreCase) ||
string.Equals(path, "/index.html", StringComparison.OrdinalIgnoreCase))
{
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
new CookieOptions() { HttpOnly = false });
}
return next(context);
});
}
public void ConfigureServices(IServiceCollection services)
{
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
}
Observação
Quando o token antifalsificação é fornecido no cabeçalho da solicitação e no conteúdo do formulário, somente o token no cabeçalho é validado.
Autenticação do Windows e cookies antifalsificação
Ao utilizar a autenticação do Windows, os pontos de extremidade do aplicativo devem ser protegidos contra ataques CSRF da mesma maneira que se faz com cookies. O navegador envia implicitamente o contexto de autenticação para o servidor e, portanto, os endpoints precisam ser protegidos contra ataques CSRF.
Estender a antifalsificação
O tipo IAntiforgeryAdditionalDataProvider permite que os desenvolvedores estendam o comportamento do sistema anti-CSRF ao arredondar dados adicionais em cada token. O método GetAdditionalData é chamado sempre que um token de campo é gerado e o valor retornado é inserido no token gerado. Um implementador pode retornar um timestamp, um nonce ou qualquer outro valor e, em seguida, chamar ValidateAdditionalData para validar esse dado quando o token for validado. O nome de usuário do cliente já está inserido nos tokens gerados, portanto, não é necessário incluir essas informações. Se um token incluir dados complementares, mas nenhum IAntiForgeryAdditionalDataProvider estiver configurado, os dados complementares não serão validados.