Sei sulla pagina 1di 9

Folha de Dicas de Segurança do .

NET
Esta página pretende fornecer dicas básicas rápidas de segurança para desenvolvedores.

O .NET Framework
O .NET Framework é a principal plataforma da Microsoft para desenvolvimento
corporativo. É a API de suporte para ASP.NET, aplicativos de área de trabalho do
Windows, serviços do Windows Communication Foundation, SharePoint, Visual Studio
Tools para Office e outras tecnologias.

Atualizando o Framework
O .NET Framework é mantido atualizado pela Microsoft com o serviço Windows
Update. Os desenvolvedores normalmente não precisam executar atualizações separadas
no Framework. A atualização do Windows pode ser acessada no Windows Update ou no
programa Windows Update em um computador Windows.
Estruturas individuais podem ser mantidas atualizadas usando o NuGet . Como o Visual
Studio solicita atualizações, construa-as em seu ciclo de vida.
Lembre-se de que as bibliotecas de terceiros precisam ser atualizadas separadamente e
nem todas usam o Nuget. O ELMAH, por exemplo, requer um esforço de atualização
separado.

Orientação do .NET Framework


O .NET Framework é o conjunto de APIs que suportam um sistema de tipos avançados,
dados, gráficos, rede, manipulação de arquivos e a maior parte do que é necessário para
criar aplicativos corporativos no ecossistema da Microsoft. É uma biblioteca quase
onipresente que tem nomes e versões fortes no nível da montagem.

Data de acesso

 Use comandos SQL parametrizados para todos os dados de acesso, sem exceção.
 Não use o SqlCommand com um parâmetro de cadeia de caracteres composto de
uma cadeia SQL concatenada .
 Whitelist valores permitidos provenientes do usuário. Use enums, TryParse ou valores
de pesquisa para garantir que os dados provenientes do usuário sejam os esperados.
 Enums ainda são vulneráveis a valores inesperados porque o .NET só valida uma
conversão bem-sucedida para o tipo de dados subjacente, integer por
padrão. Enum.IsDefined pode validar se o valor de entrada é válido dentro da lista
de constantes definidas.
 Aplique o princípio do menor privilégio ao configurar o usuário do banco de dados no
banco de dados de sua escolha. O usuário do banco de dados só deve poder acessar
itens que façam sentido para o caso de uso.
 O uso do Entity Framework é um mecanismo de prevenção de injeção de SQL muito
eficaz . Lembre-se de que criar suas próprias consultas ad hoc no EF é tão suscetível
ao SQLi quanto uma consulta SQL simples.
 Ao usar o SQL Server, prefira a autenticação integrada pela autenticação do SQL.
 Use Sempre Criptografado sempre que possível para dados confidenciais (SQL Server
2016 e SQL Azure),
Encriptação

 Nunca, nunca escreva sua própria criptografia.


 Use a API de proteção de dados do Windows (DPAPI) para armazenamento local
seguro de dados confidenciais.
 Use um algoritmo de hash forte.
 No .NET (tanto o Framework quanto o Core), o algoritmo de hash mais forte para
requisitos gerais de hashing é System.Security.Cryptography.SHA512 .
 Na estrutura .NET, o algoritmo mais forte para hashing de senha é PBKDF2,
implementado como System.Security.Cryptography.Rfc2898DeriveBytes .
 No .NET Core, o algoritmo mais forte para hashing de senha é o PBKDF2,
implementado
como Microsoft.AspNetCore.Cryptography.KeyDerivation.Pbkdf2, que possui
várias vantagens significativas sobre o Rfc2898DeriveBytes.
 Ao usar uma função de hash para inserir entradas não exclusivas, como senhas,
use um valor de sal adicionado ao valor original antes do hashing.
 Certifique-se de que seu aplicativo ou protocolo possa suportar facilmente uma
mudança futura de algoritmos criptográficos.
 Use o Nuget para manter todos os seus pacotes atualizados. Assista as atualizações
em sua configuração de desenvolvimento e planeje atualizações para seus aplicativos
de acordo.
Geral

 Bloqueie o arquivo de configuração.


 Remova todos os aspectos da configuração que não estão em uso.
 Criptografar partes sensíveis do web.config usando aspnet_regiis -pe

 Para aplicativos Click Once, o .Net Framework deve ser atualizado para usar a versão
4.6.2 para garantir o suporte ao TLS 1.1 / 1.2.

Orientação de Formulários da Web ASP.NET


O ASP.NET Web Forms é a API de desenvolvimento de aplicativos baseada em
navegador original para o .NET framework e ainda é a plataforma corporativa mais comum
para o desenvolvimento de aplicativos da Web.

 Sempre use HTTPS .


 Ative o requireSSL em cookies e elementos de formulário e HttpOnly em cookies no
web.config.
 Implemente customErrors .
 Certifique-se de que o rastreio esteja desativado.
 Embora o viewstate nem sempre seja apropriado para o desenvolvimento da Web, seu
uso pode fornecer mitigação de CSRF. Para tornar o ViewState protegido contra
ataques de CSRF, você precisa definir o ViewStateUserKey :

protected override OnInit(EventArgs e) {


base.OnInit(e);
ViewStateUserKey = Session.SessionID;
}

Se você não usar o Viewstate, consulte a página mestra padrão do modelo padrão do
ASP.NET Web Forms para obter um token anti-CSRF manual usando um cookie de envio
duplo.
private const string AntiXsrfTokenKey = "__AntiXsrfToken";
private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
private string _antiXsrfTokenValue;
protected void Page_Init (object sender, EventArgs e) {
// The code below helps to protect against XSRF attacks
var requestCookie = Request.Cookies[AntiXsrfTokenKey];
Guid requestCookieGuidValue;
if (requestCookie != null && Guid.TryParse (requestCookie.Value, out
requestCookieGuidValue)) {
// Use the Anti-XSRF token from the cookie
_antiXsrfTokenValue = requestCookie.Value;
Page.ViewStateUserKey = _antiXsrfTokenValue;
} else {
// Generate a new Anti-XSRF token and save to the cookie
_antiXsrfTokenValue = Guid.NewGuid ().ToString ("N");
Page.ViewStateUserKey = _antiXsrfTokenValue;
var responseCookie = new HttpCookie (AntiXsrfTokenKey) {
HttpOnly = true,
Value = _antiXsrfTokenValue
};
if (FormsAuthentication.RequireSSL && Request.IsSecureConnection)
{
responseCookie.Secure = true;
}
Response.Cookies.Set (responseCookie);
}
Page.PreLoad += master_Page_PreLoad;
}

protected void master_Page_PreLoad (object sender, EventArgs e) {


if (!IsPostBack) {
// Set Anti-XSRF token
ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
ViewState[AntiXsrfUserNameKey] = Context.User.Identity.Name ??
String.Empty;
} else {
// Validate the Anti-XSRF token
if ((string) ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
||

(string) ViewState[AntiXsrfUserNameKey] !=
(Context.User.Identity.Name ?? String.Empty)) {
throw new InvalidOperationException ("Validation of Anti-XSRF
token failed.");
}
}
}
Considere o HSTS no IIS.

 No painel Conexões, acesse o site, aplicativo ou diretório para o qual você deseja
definir um cabeçalho HTTP personalizado.
 No painel Início, clique duas vezes em Cabeçalhos de Resposta HTTP.
 No painel Cabeçalhos de Resposta HTTP, clique em Adicionar ... no painel Ações.
 Na caixa de diálogo Adicionar cabeçalho de resposta HTTP personalizado, defina o
nome e o valor do cabeçalho personalizado e clique em OK.
 Esta é uma configuração web.config recomendada que lida com HSTS entre outras
coisas.

<?xml version="1.0" encoding="UTF-8"?>


<configuration>
<system.web>
<httpRuntime enableVersionHeader="false"/>
</system.web>
<system.webServer>
<security>
<requestFiltering removeServerHeader="true" />
</security>
<staticContent>
<clientCache cacheControlCustom="public"
cacheControlMode="UseMaxAge" cacheControlMaxAge="1.00:00:00"
setEtag="true" />
</staticContent>
<httpProtocol>
<customHeaders>
<add name="Content-Security-Policy" value="default-src 'none';
style-src 'self'; img-src 'self'; font-src 'self'" />
<add name="X-Content-Type-Options" value="NOSNIFF" />
<add name="X-Frame-Options" value="DENY" />
<add name="X-Permitted-Cross-Domain-Policies" value="master-
only"/>
<add name="X-XSS-Protection" value="1; mode=block"/>
<remove name="X-Powered-By"/>
</customHeaders>
</httpProtocol>
<rewrite>
<rules>
<rule name="Redirect to https">
<match url="(.*)"/>
<conditions>
<add input="{HTTPS}" pattern="Off"/>
<add input="{REQUEST_METHOD}" pattern="^get$|^head$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}"
redirectType="Permanent"/>
</rule>
</rules>
<outboundRules>
<rule name="Add HSTS Header" enabled="true">
<match serverVariable="RESPONSE_Strict_Transport_Security"
pattern=".*" />
<conditions>
<add input="{HTTPS}" pattern="on" ignoreCase="true" />
</conditions>
<action type="Rewrite" value="max-age=15768000" />
</rule>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>

 Remova o cabeçalho da versão.


<httpRuntime enableVersionHeader = "false"/>

 Remova também o cabeçalho do servidor.


HttpContext.Current.Response.Headers.Remove("Server");

Validação HTTP e codificação

 Não desative validateRequest no web.config ou na configuração da página. Esse valor


permite a proteção XSS limitada no ASP.NET e deve ser deixado intacto, pois fornece
prevenção parcial de scripts entre sites. A validação completa da solicitação é
recomendada além das proteções incorporadas.
 A versão 4.5 do .NET Frameworks inclui a biblioteca AntiXssEncoder, que possui uma
biblioteca de codificação de entrada abrangente para a prevenção de XSS. Use-o.
 Valores permitidos da lista de permissões a qualquer momento que a entrada do
usuário for aceita.
 Valide o formato de URI usando Uri.IsWellFormedUriString .
Autenticação de formulários

 Use cookies para persistência quando possível. O Cookieless Auth será o padrão para
UseDeviceProfile.
 Não confie no URI da solicitação de persistência da sessão ou autorização. Pode ser
facilmente falsificado.
 Reduza o tempo limite de autenticação de formulários do padrão de 20 minutos para o
período mais curto apropriado para seu aplicativo. Se slidingExpiration for usado, esse
tempo limite será redefinido após cada solicitação, para que os usuários ativos não
sejam afetados.
 Se HTTPS não for usado, o slideExpiration deverá ser desativado. Considere
desabilitar o slidingExpiration mesmo com HTTPS.
 Sempre implemente controles de acesso adequados.
 Compare o nome de usuário fornecido pelo usuário com User.Identity.Name.
 Verifique as funções em relação a User.Identity.IsInRole.
 Use o provedor de associação do ASP.NET e o provedor de função, mas revise o
armazenamento de senha. O armazenamento padrão hashes a senha com uma única
iteração de SHA-1, que é bastante fraca. O modelo ASP.NET MVC4 usa o ASP.NET
Identity em vez de ASP.NET Membership e o ASP.NET Identity usa PBKDF2 por
padrão, o que é melhor. Revise a folha de dicas do OWASP Password Storagepara
obter mais informações.
 Explicitamente autorize solicitações de recursos.
 Utilize a autorização baseada em função usando User.Identity.IsInRole.

Orientação da ASP.NET MVC


A ASP.NET MVC (Model-View-Controller) é uma estrutura de aplicativos da web
contemporânea que usa uma comunicação HTTP mais padronizada do que o modelo de
postback do Web Forms. O OWASP Top 10 lista as ameaças mais comuns e perigosas
para a segurança da Web no mundo atual e é revisado a cada 3 anos. Esta seção é
baseada nisso. Sua abordagem para proteger seu aplicativo da Web deve ser começar
com a ameaça superior A1 abaixo e trabalhar para baixo. Isso garantirá que o tempo gasto
em segurança seja gasto com mais eficiência e cubra as ameaças principais primeiro e
depois as ameaças menores. Depois de cobrir o top 10, é geralmente aconselhável avaliar
outras ameaças ou obter um Teste de Penetração profissionalmente concluído.

 A1 Injeção SQL
DO: O uso de um mapeador relacional de objeto (ORM) ou de procedimentos
armazenados é a maneira mais eficiente de combater a vulnerabilidade de Injeção de
SQL.
DO: Use consultas parametrizadas em que uma consulta SQL direta deve ser usada.
Por exemplo, em estruturas de entidades:
var sql = @"Update [User] SET FirstName = @FirstName WHERE Id = @Id";
context.Database.ExecuteSqlCommand (
sql,
new SqlParameter ("@FirstName", firstname),
new SqlParameter ("@Id", id));
NÃO: concatenar cadeias de caracteres em qualquer parte do código e executá-las no
banco de dados (conhecido como SQL dinâmico). NB: Você ainda pode fazer isso
acidentalmente com ORMs ou procedimentos armazenados, portanto, verifique em todos
os lugares.
por exemplo:
string strQry = "SELECT * FROM Users WHERE UserName='" + txtUser.Text +
"' AND Password='" + txtPassword.Text + "'";
EXEC strQry // SQL Injection vulnerability!

FAZER: Praticar o menor privilégio - Conecte-se ao banco de dados usando uma conta
com um conjunto mínimo de permissões necessárias para executar seu trabalho, ou seja,
não a conta sa

 Gerenciamento de Conta A2 Fraco


Garantir que os cookies sejam enviados via httpOnly:
CookieHttpOnly = true,

Reduza o período de tempo em que uma sessão pode ser roubada, reduzindo o tempo
limite da sessão e removendo a expiração de deslizamento:
ExpireTimeSpan = TimeSpan.FromMinutes(60),
SlidingExpiration = false

Veja aqui o snippet de código de inicialização completo


Garantir que o cookie seja enviado por https no ambiente de produção. Isso deve ser
imposto nas transformações de configuração:
<httpCookies requireSSL="true"
xdt:Transform="SetAttributes(requireSSL)"/>
<authentication>
<forms requireSSL="true" xdt:Transform="SetAttributes(requireSSL)"/>
</authentication>

Proteger os métodos Logon, Registro e redefinição de senha contra ataques de força bruta
por meio de solicitações de limitação (consulte o código abaixo), considere também usar o
ReCaptcha.

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
[AllowXRequestsEveryXSecondsAttribute (Name = "LogOn", Message = "You
have performed this action more than {x} times in the last {n} seconds.",
Requests = 3, Seconds = 60)]
public async Task<ActionResult> LogOn (LogOnViewModel model, string
returnUrl)

Encontre aqui o código para evitar a limitação


NÃO: Role seu próprio gerenciamento de autenticação ou sessão, use o fornecido pelo
.Net
NÃO: Diga a alguém se a conta existe em Logon, Registro ou Redefinição de senha. Diga
algo como "O nome de usuário ou senha estava incorreto" ou "Se essa conta existir, um
token de redefinição será enviado para o endereço de e-mail registrado". Isso protege
contra enumeração de conta. O feedback para o usuário deve ser idêntico, quer a conta
exista ou não, tanto em termos de conteúdo quanto de comportamento: por exemplo, se a
resposta demorar 50% a mais quando a conta é real, as informações de associação
podem ser adivinhadas e testadas.

 Scripts de site cruzado A3


NÃO: Confie em quaisquer dados que o usuário lhe enviar, prefira listas brancas (sempre
seguras) em listas negras
Você obtém a codificação de todo o conteúdo HTML com o MVC3 para codificar
corretamente todo o conteúdo, seja HTML, JavaScript, CSS, LDAP, etc., use a biblioteca
do Microsoft AntiXSS:

Install-Package AntiXSS
então defina em config:

<system.web>
<httpRuntime targetFramework="4.5"
enableVersionHeader="false"
encoderType="Microsoft.Security.Application.AntiXssEncoder,
AntiXssLibrary" maxRequestLength="4096" />

NÃO: Use o atributo [AllowHTML] ou a classe auxiliar @ Html.Raw, a menos que você
realmente saiba que o conteúdo que está sendo gravado no navegador é seguro e que foi
escapado corretamente.
DO: Habilite uma política de segurança de conteúdo, isso impedirá que suas páginas
acessem ativos que não devem ser capazes de acessar (por exemplo, um script mal-
intencionado):

<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Content-Security-Policy" value="default-
src 'none'; style-src 'self'; img-src 'self'; font-src 'self';
script-src 'self'" />
...

 Referências ao objeto A4 Insecure Direct


Quando você tem um recurso (objeto) que pode ser acessado por uma referência (no
exemplo abaixo, este é o id), então você precisa garantir que o usuário deve estar lá
// Insecure
public ActionResult Edit (int id) {
var user = _context.Users.FirstOrDefault (e => e.Id == id);
return View ("Details", new UserViewModel (user);
}

// Secure
public ActionResult Edit (int id) {
var user = _context.Users.FirstOrDefault (e => e.Id == id);
// Establish user has right to edit the details
if (user.Id != _userIdentity.GetUserId ()) {
HandleErrorInfo error = new HandleErrorInfo (new Exception
("INFO: You do not have permission to edit these details"));
return View ("Error", error);
}
return View ("Edit", new UserViewModel (user);
}

Potrebbero piacerti anche