ASP.NET Core - 10 práticas para segurança em aplicações MVC - I


Hoje vou iniciar apresentação de 10 dicas úteis que podemos usar para tornar mais seguras as aplicações ASP .NET Core MVC.

O ASP.NET Core MVC é um framework para desenvolver aplicações web, sendo muito usado por desenvolvedores em todo o mundo.

No entanto, esses aplicativos web podem sofrer ataques de diferentes fontes, e é nossa responsabilidade proteger a aplicação e os dados.

Neste  artigo veremos algumas práticas recomendadas para evitar vulnerabilidades em aplicações ASP .NET Core MVC.

1- Cross-Site Scriptint (XSS)

O que é Cross-Site Scripting ?

A injeção de um script malicioso no campo de entrada de formulário de uma página da Web com a intenção de roubar informações confidenciais, como credenciais de login ou outras informações de autenticação, cookies e valores de sessão, é chamado de ataque de script entre sites (XSS).

A injeção de script pode ser realizada das seguintes formas:

Como evitar scripts entre sites (XSS) ?

Os ataques de script entre sites podem ser evitados das seguintes maneiras:

a- Atributos de expressão regular

Você pode usar expressões regulares para validar as entradas de formulário do usuário. Dessa forma, você pode negar símbolos e caracteres maliciosos ou permitir apenas caracteres obrigatórios aceitáveis ​​no campo de entrada antes de permitir que o usuário prossiga.

b - Modelo de objeto de expressão regular

Assim como o atributo de expressão regular, usando o modelo de objeto de expressão regular, você pode validar as entradas do usuário chamando métodos estáticos da classe Regex. (Você pode fazer validações de entrada do lado do cliente e do lado do servidor.)

c - Codificação HTML

O mecanismo MVC Razor codifica automaticamente todas as entradas para que a parte do script fornecida em qualquer campo nunca seja executada.

Nota: Se você deseja usar texto bruto sem codificação, deve usar a sintaxe @Html.Raw().

d- Codificação de URL

Normalmente, usamos texto simples em strings de consulta de URL, que podem ser usadas para lançar ataques XSS. Portanto, devemos codificar a entrada do parâmetro de consulta na URL. Temos uma biblioteca integrada no NuGet para codificar e decodificar o texto presente no namespace System.Net.

Exemplo :

string encodedValue = System.Net.WebUtility.UrlEncode("raw-string-text");
string decodedValue = System.Net.WebUtility.UrlDecode(encodedValue);

2- SQL Injection

O que é SQL Injection?

É um ataque perigoso em que usuários não autorizados injetam código SQL malicioso que é executado em seu banco de dados, permitindo que os invasores acessem informações confidenciais nele armazenadas.

O ataque de injeção de SQL pode ser evitado das seguintes maneiras:

- Validar entradas de dados;
- Usar procedimentos armazenados;
- Usar consultas parametrizadas;
- Usar o  Entity Framework ou qualquer outro ORM;
- Usar o acesso ao banco de dados com menos privilégios;
- Armazenar dados criptografados;


Validar entradas

A defesa contra injeção de SQL por meio da validação de entradas requer as seguintes ações:

- Validar as entradas do usuário no lado do cliente e no lado do servidor;
- Não permitir caracteres especiais envolvidos em scripts SQL;
- Usar expressões regulares e anotações de dados para validar as entradas;

Usar procedimentos armazenados

O uso de procedimentos armazenados impedirá a injeção de SQL, mas ainda devemos validar os parâmetros de entrada passados ​​para os procedimentos armazenados.

Usar consultas parametrizadas

Se quiser usar consultas inline, você deve usar consultas parametrizadas para evitar injeção de SQL. O exemplo de código a seguir mostra uma consulta parametrizada.

string sqlText = @"UPDATE Customer
   SET Name = @NewName, Age = @NewAge
   WHERE ID = @RecordID";

SqlCommand dbCommand = new SqlCommand(sqlText, existingSqlConnection);

Usar Entity Framework ou qualquer outro ORM

O acrônimo ORM significa mapeador objeto-relacional, que mapeia objetos SQL para seu objeto de classe na sua aplicação.

Se você estiver usando o Entity framework corretamente, não estará sujeito a ataques de injeção de SQL porque o Entity Framework usa internamente consultas parametrizadas.

Usar o acesso ao banco de dados com menos privilégios

Devemos limitar as permissões do usuário do banco de dados para tabelas que contêm dados confidenciais. Por exemplo, devemos restringir as permissões de inserção, atualização e exclusão para tabelas relacionadas a pagamentos e transações, e também devemos limitar as permissões para tabelas que armazenam informações pessoais de um usuário.

Se um usuário trabalha apenas com consultas Select, devemos dar permissão apenas para a instrução Select e não devemos fornecer permissões para as instruções Insert, Update e Delete.

Armazenar dados criptografados

Não devemos armazenar informações confidenciais, como endereços de e-mail e senhas, como texto simples em um banco de dados. Ele deve ser armazenado em um formato criptografado usando ou não um hashing.

O Hashing refere-se à conversão permanente de dados em resumo da mensagem enquanto a criptografia funciona de duas maneiras, que podem codificar e decodificar os dados. O hash ajuda a proteger a integridade das informações e a criptografia é usada para proteger os dados do alcance de terceiros.

3 - Cross-Site Request Forgery(CSRF)

O que é Cross-Site Request Forgery ou falsificação de solicitação entre sites ?

O Cross-Site Request Forgery ocorre quando um invasor atua como uma fonte confiável e envia alguns dados falsificados para um site. O site processa os dados falsificados porque acredita que eles vêm de uma fonte confiável.

Vamos discutir um exemplo desse tipo de ataque: quando um usuário transfere fundos de uma conta bancária para outra, uma conexão confiável é estabelecida entre o usuário e o site do banco depois que o usuário efetua login com sucesso.

Ao mesmo tempo, o usuário clica em um link malicioso em um e-mail enviado por um invasor.

Como a sessão segura já foi estabelecida entre o usuário e o site do banco, o invasor usa essa conexão e executa algumas atividades maliciosas, como transferências de fundos.

No entanto, esse ataque é um risco apenas no lado do servidor (aplicativo da web), não no lado do usuário final.

Como evitar falsificação de solicitação entre sites

Podemos evitar esse ataque usando AntiForgeryToken que
é um método que gera e insere no HTML gerado na view um código para evitar que se falsifique o envio de dados para o servidor.

Podemos usar o tag-helper HTML asp-antiforgery em um atributo HTML e definir seu valor como true. Por padrão, este valor será falso. Se definirmos esse valor como verdadeiro, ele gerará um token anti-falsificação. Em seguida, precisamos adicionar o atributo [ValidateAntiForgeryToken] ao método de pós-ação do formulário para verificar se um token válido é gerado.

Nota: Apesar de ser permitido não é necessário declarar o AntiForgeryToken na View, pois toda View Razor é protegida automaticamente de CSRF e será gerado um input hidden com o “__RequestVerificationToken” a cada requisição.

4- Página de erro personalizada para tratamento de erros

Devemos criar uma página de erro personalizada onde evitamos informar os detalhes dos erros que porventura podem ocorrer na aplicação.

Com isso evitamos a expor aos usuários informações confidenciais, como informações de configuração do banco de dados, nomes de tabelas, procedimentos armazenados, estruturas de dados e estrutura de codificação de programação.

Para o usuário final devemos exibir apenas mensagens amigáveis com orientações de procedimentos a serem executados.

Como adicionar tratamento de erros personalizado adequado

Existem duas maneiras de adicionar páginas personalizadas de tratamento de erros em um aplicativo ASP.NET Core.

A primeira abordagem é criar um atributo de tratamento de erros personalizado usando ExceptionFilterAttribute. Este atributo tratará da exceção.

Podemos substituir o método OnException e gravar exceções em arquivos de texto organizados por data e, em seguida, armazenar os arquivos em um caminho de pasta desejado. Também podemos armazenar a exceção em um banco de dados. Por fim, redirecionaremos a rota para uma página de erro personalizada.

A segunda abordagem é configurar UseExceptionHandler no ambiente de produção.

Nesta abordagem, escrevemos um código para mostrar a página de erro customizada no controlador de erro apenas se o ambiente de hospedagem for  o ambiente de produção, portanto, os ambientes de teste e desenvolvimento não mostrarão a página de erro customizada, mas em vez disso mostrarão o erro real no navegador.

5- Ocultar a versão da aplicação

Devemos ocultar as informações de versão que usamos para desenvolver nossa aplicação dos usuários finais, porque se um invasor conhecer a versão, ele pode tentar direcionar um ataque a essa versão específica com base em uma vulnerabilidade previamente divulgada.

Sempre que o navegador envia uma solicitação HTTP ao servidor, em resposta, o navegador obtém um cabeçalho de resposta, que contém as seguintes informações:

a- server
b- x-powered-by
c- x-aspnet-version
d- x-aspnetmvc-version
e- x-sourcefiles


O servidor mostra informações sobre o servidor da web usado. Por exemplo, uma resposta pode conter o seguinte:

Server: Microsoft-IIS/10.0 : O aplicativo é hospedado pelo Microsoft-IIS versão 10.0.
X-Powered-By: ASP.NET : Mostra o framework ASP.NET na qual seu site está sendo executado;
X-Aspnet-Version : 4.0.30319: Mostra a versão da  ASP.NET em que seu site está sendo executado.
X-AspnetMvc-Version : 4.0: Mostra a versão da ASP.NET MVC em que seu site está sendo executado.
X-SourceFiles : Será gerado apenas para solicitações de host local e serve para fins de depuração.

Como ocultar valores de cabeçalho - Header do Servidor

Podemos remover o cabeçalho do servidor adicionando a linha

“UseKestrel (c => c.AddServerHeader = false)”

no método CreateWebHostBuilder na classe Program.cs.

Para remover o cabeçalho X-Powered-By, precisamos adicionar um arquivo de configuração web (web.config), e nesse arquivo de configuração , precisamos adicionar um elemento que remove o elemento X-Powered-By na tag <system.webServer>.

<system.webServer>
  <httpProtocol>
     <customHeaders>
     <remove name = "X-Powered-By" />
     <customHeaders>
  </httpProtocol>
</system.webServer>
 

Para remover o cabeçalho X-Aspnet-Version, faça a seguinte alteração no arquivo de configuração da web :.

<system.web>
     </httpRuntime enableVersionHeader = false >
</system.web>
 

Na segunda parte do artigo veremos mais 5 dicas para segurança nas aplicações ASP .NET Core MVC.

"Se o SENHOR não edificar a casa, em vão trabalham os que a edificam; se o SENHOR não guardar a cidade, em vão vigia a sentinela."
Salmos 127:1

Referências:


José Carlos Macoratti