Por framework
Segurança do ASP.NET Core — uma referência de hardening de produção
Uma referência de hardening de produção para ASP.NET Core: um checklist por prioridade mais erros de produção, segredos (User Secrets/Key Vault), CVEs do NuGet, autorização, over-posting, desserialização e SSRF. Defensivo, sem passos de ataque.
Para: qualquer pessoa que opere um app ou API no ASP.NET Core. Sem passos de ataque aqui — esta é uma referência de trabalho para hardening: um checklist ordenado por prioridade, orientação por área e autoverificação. Para o panorama entre frameworks, veja o hub de segurança por framework.
Checklist de hardening ordenado por prioridade
Faça esta tabela de cima para baixo. P0 é um pré-requisito, P1 é a fonte mais frequente de incidentes, P2 é higiene operacional contínua.
P0 ── Pré-requisito (faça primeiro)
Sem erros detalhados em produção / externalize os segredos / corrija rápido os CVEs de dependências NuGet
P1 ── Principal fonte de incidentes
Autorização ([Authorize], default-deny, proprietário) / defesa contra over-posting (DTOs/[Bind])
P2 ── Higiene operacional
Desserialização insegura / HTTPS, headers, antiforgery / SSRF
| Prioridade | Controle | Especificidades (ASP.NET Core) |
|---|---|---|
| P0 | Erros de produção | UseExceptionHandler. Não mostre a Developer Exception Page/detalhes em prod (verificação de env correta) |
| P0 | Externalize os segredos | Não fixe no appsettings.json. Dev = User Secrets, prod = env/Key Vault |
| P0 | CVEs de dependências NuGet | Monitore com dotnet list package --vulnerable/osv-scanner; julgue pela versão em execução, corrija rápido |
| P1 | Autorização explícita | [Authorize] + default-deny (fallback policy) + verificações baseadas em recurso/proprietário |
| P1 | Defesa contra over-posting | Faça bind a um DTO, não à entidade diretamente. Use [Bind] para limitar os campos aceitos |
| P2 | Desserialização | Não use BinaryFormatter. Não restaure dados não confiáveis com um formato inseguro |
| P2 | HTTPS/headers/CSRF | UseHttpsRedirection, UseHsts, antiforgery (CSRF), atributos de cookie |
| P2 | SSRF | Allowlist para buscas server-side + bloqueie IPs internos/metadados |
1. Exposição de erros em produção (P0)
- Em produção, mude para um erro genérico via
UseExceptionHandlere não mostre a Developer Exception Page/detalhes (acerte a verificação de ambiente, ex.:ASPNETCORE_ENVIRONMENT=Production). - Não vaze stack traces ou estrutura interna externamente.
2. Externalize os segredos (P0)
- Não fixe connection strings ou chaves no appsettings.json. Use User Secrets em desenvolvimento e variáveis de ambiente ou um gerenciador de segredos na nuvem (Key Vault) em produção.
- O appsettings.json vaza facilmente via commit acidental ou exposição. Não faça commit dele no repositório nem o coloque em um diretório público (→ mantenha segredos fora dos diretórios públicos). Rotacione prontamente se vazar.
3. CVEs de dependências NuGet (P0)
- Monitore por máquina os CVEs conhecidos com
dotnet list package --vulnerableou osv-scanner, julgue pela versão em execução e corrija rápido (→ monitorar CVEs de dependências · o manual de resposta a vulnerabilidades). - Mantenha o .NET em uma versão suportada e não deixe versões EOL no lugar.
4. Autorização (P1 — a principal fonte)
Comum (perigoso)
- esquecer o
[Authorize]em um endpoint - autenticado, mas sem verificação de proprietário
- padrão inclina para "permitir", não autenticado passa
- sem design de role/policy, verificações ad-hoc
Correto
[Authorize]+ default-deny via uma fallback policy- baseado em role/policy + autorização baseada em recurso para propriedade
- verificado em cada caminho de leitura/atualização/exclusão
- autorização construída explicitamente, não deixada aos padrões
Veja o que é IDOR. Autenticação e autorização diferem; autorize perto dos dados.
5. Over-posting (P1)
- Não faça bind de entidades diretamente. Faça bind a um DTO apenas de entrada e aceite somente os campos de que você precisa.
- Ou use
[Bind]para limitar explicitamente os campos aceitos. Não deixe uma flag de privilégio ser sobrescrita a partir de entrada externa.
6. Desserialização insegura e entrada (P2)
- Não use
BinaryFormatter(obsoleto/inseguro). Não restaure dados não confiáveis com um formato inseguro (pode levar a RCE sob as condições certas) (→ o que é RCE). - Valide a entrada com validação de modelo (data annotations, etc.) quanto a tipo/faixa/valores permitidos antes de usar.
7. HTTPS, headers, antiforgery (P2)
- Use
UseHttpsRedirection+UseHstspara forçar HTTPS, e marque os cookies como secure/httponly/samesite. - Use tokens antiforgery (defesa CSRF) em formulários/requisições que alteram estado (→ o que é CSRF).
- Adicione headers de segurança (verifique o seu próprio site com o verificador de headers de segurança).
8. SSRF e buscas server-side (P2)
- A busca server-side (
HttpClient, etc.) de URLs fornecidas pelo usuário deve restringir os alvos a uma allowlist e bloquear o alcance a IPs internos/metadados (→ o que é SSRF). Valide os uploads e armazene-os fora da superfície pública.
Verifique: o seu ASP.NET Core está realmente protegido?
Construir não é o fim — só está pronto quando você verificou. Estas são autoverificações defensivas contra o seu próprio ambiente.
Nenhuma Developer Exception Page em produção
Segredos não estão na config/repositório
appsettings.json e que nenhum segredo está no repositório.A autorização se sustenta
Dependências e HTTPS/headers
dotnet list package --vulnerable/osv está limpo e que HTTPS/HSTS estão presentes via o verificador de headers.A visão deste site: mesmo sobre uma fundação sólida, as configurações e a autorização são sua responsabilidade
O ASP.NET Core tem mecanismos sólidos para autenticação, autorização e proteção de dados, mas as configurações de produção e a aplicação da autorização são coisas que você precisa acertar por ambiente e por endpoint. Este site é uma stack diferente, mas o princípio é o mesmo: não vaze detalhes internos em produção, mantenha os segredos fora da config, sempre escreva autorização nos pontos de entrada públicos e monitore as dependências por CVEs. Uma fundação sólida só compensa com configurações corretas e autorização explícita.
Leia a seguir
- Hub: segurança por framework · segurança do Spring Boot (também corporativo, forma de dependências/autorização parecida)
- Prática: o manual de resposta a vulnerabilidades · monitorar CVEs de dependências · mantenha segredos fora dos diretórios públicos
- Glossário: o que é IDOR · o que é RCE · CSRF · SSRF
- Ferramentas: verificador de headers de segurança
FAQ
QO que eu devo fazer primeiro para proteger o ASP.NET Core?
Os três itens P0: (1) não mostre a Developer Exception Page / erros detalhados em produção (UseExceptionHandler, verificação de ambiente correta); (2) externalize os segredos em vez de fixá-los no appsettings.json (User Secrets em dev, variáveis de ambiente ou Key Vault em prod); (3) monitore por máquina os CVEs de dependências NuGet e corrija rápido, julgando pela versão em execução. Em seguida, avance para a autorização ([Authorize], default-deny) e as defesas contra over-posting.
QOnde os segredos (connection strings, chaves de API) devem ficar?
A regra é: não fixados no appsettings.json. Em desenvolvimento use User Secrets; em produção carregue de variáveis de ambiente ou de um gerenciador de segredos na nuvem (Key Vault). O appsettings.json tende a acabar no repositório e vaza facilmente via um diretório público ou um commit acidental. Se um vazar, rotacione a connection string ou a chave prontamente.
QComo evito esquecer os atributos de autorização?
Esqueça o [Authorize] em um controller ou endpoint e qualquer um pode alcançá-lo sem autenticação. Incline o padrão para negar (uma fallback policy que rejeita requisições não autenticadas), torne as permissões explícitas com autorização baseada em role/policy e escreva verificações de proprietário do recurso (autorização baseada em recurso). Não pare em 'logado = permitido' — verifique também o proprietário do alvo.
QO que é over-posting?
Se o model binding aceita todos os campos em uma entidade, campos inesperados que o usuário enviou (como uma flag de privilégio) podem ser sobrescritos — isso é over-posting. A correção é fazer bind a um DTO apenas de entrada, ou usar [Bind] para limitar explicitamente os campos aceitos. Não faça bind de entidades diretamente.
QPor que a desserialização insegura é perigosa?
Restaurar dados não confiáveis com um desserializador inseguro como o BinaryFormatter pode, sob as condições certas, levar à execução remota de código (RCE). O BinaryFormatter é considerado obsoleto/inseguro — não o use. Verifique a procedência dos dados de origem externa e restrinja a um formato seguro (ex.: JSON corretamente configurado) onde necessário.