Partilhar via


Quadro de segurança: Validação de entrada | Atenuações

Produto/Serviço Artigo
Aplicação Web
Base de dados
API Web
Banco de Dados de Documentos do Azure
WCF

Desabilitar scripts XSLT para todas as transformações usando folhas de estilo não confiáveis

Cargo Detalhes
Componente Aplicação Web
Fase SDL Criar
Tecnologias aplicáveis Genérico
Atributos N/A
Referências Segurança XSLT, propriedade XsltSettings.EnableScript
Passos XSLT suporta scripts dentro de folhas de estilo usando o <msxml:script> elemento . Isso permite que funções personalizadas sejam usadas em uma transformação XSLT. O script é executado sob o contexto do processo que executa a transformação. O script XSLT deve ser desabilitado quando estiver em um ambiente não confiável para impedir a execução de código não confiável. Se estiver usando o .NET: o script XSLT está desabilitado por padrão, no entanto, você deve garantir que ele não tenha sido explicitamente habilitado por meio da XsltSettings.EnableScript propriedade.

Exemplo

XsltSettings settings = new XsltSettings();
settings.EnableScript = true; // WRONG: THIS SHOULD BE SET TO false

Exemplo

Se você estiver usando o MSXML 6.0, o script XSLT será desabilitado por padrão; no entanto, você deve garantir que ele não tenha sido explicitamente habilitado por meio da propriedade de objeto DOM XML AllowXsltScript.

doc.setProperty("AllowXsltScript", true); // WRONG: THIS SHOULD BE SET TO false

Exemplo

Se você estiver usando o MSXML 5 ou inferior, o script XSLT está habilitado por padrão e você deve desativá-lo explicitamente. Defina a propriedade do objeto DOM XML AllowXsltScript como false.

doc.setProperty("AllowXsltScript", false); // CORRECT. Setting to false disables XSLT scripting.

Certifique-se de que cada página que possa conter conteúdo controlável pelo usuário desative a deteção automática de MIME

Cargo Detalhes
Componente Aplicação Web
Fase SDL Criar
Tecnologias aplicáveis Genérico
Atributos N/A
Referências Segurança do IE8 Parte V - Proteção abrangente
Passos

Para cada página que possa conter conteúdo controlável pelo usuário, você deve usar o cabeçalho X-Content-Type-Options:nosniffHTTP . Para cumprir esse requisito, você pode definir o cabeçalho necessário página por página apenas para as páginas que podem conter conteúdo controlável pelo usuário ou pode defini-lo globalmente para todas as páginas do aplicativo.

Cada tipo de arquivo entregue a partir de um servidor Web tem um tipo MIME associado (também chamado de tipo de conteúdo) que descreve a natureza do conteúdo (ou seja, imagem, texto, aplicativo, etc.)

O cabeçalho X-Content-Type-Options é um cabeçalho HTTP que permite aos desenvolvedores especificar que seu conteúdo não deve ser detetado por MIME. Este cabeçalho foi projetado para mitigar ataques MIME-Sniffing. Suporte para este cabeçalho foi adicionado no Internet Explorer 8 (IE8)

Somente os usuários do Internet Explorer 8 (IE8) se beneficiarão do X-Content-Type-Options. Versões anteriores do Internet Explorer atualmente não respeitam o cabeçalho X-Content-Type-Options

O Internet Explorer 8 (e posterior) são os únicos navegadores importantes a implementar um recurso de desativação de deteção de MIME. Se e quando outros navegadores importantes (Firefox, Safari, Chrome) implementarem recursos semelhantes, esta recomendação será atualizada para incluir sintaxe para esses navegadores também

Exemplo

Para habilitar o cabeçalho necessário globalmente para todas as páginas do aplicativo, siga um destes procedimentos:

  • Adicione o cabeçalho no arquivo web.config se o aplicativo estiver hospedado pelo IIS (Serviços de Informações da Internet) 7
<system.webServer> 
  <httpProtocol> 
    <customHeaders> 
      <add name=""X-Content-Type-Options"" value=""nosniff""/>
    </customHeaders>
  </httpProtocol>
</system.webServer> 
  • Adicione o cabeçalho através do Application_BeginRequest global
void Application_BeginRequest(object sender, EventArgs e)
{
  this.Response.Headers[""X-Content-Type-Options""] = ""nosniff"";
} 
  • Implementar módulo HTTP personalizado
public class XContentTypeOptionsModule : IHttpModule 
  {
    #region IHttpModule Members 
    public void Dispose() 
    { 

    } 
    public void Init(HttpApplication context)
    { 
      context.PreSendRequestHeaders += newEventHandler(context_PreSendRequestHeaders); 
    } 
    #endregion 
    void context_PreSendRequestHeaders(object sender, EventArgs e) 
      { 
        HttpApplication application = sender as HttpApplication; 
        if (application == null) 
          return; 
        if (application.Response.Headers[""X-Content-Type-Options ""] != null) 
          return; 
        application.Response.Headers.Add(""X-Content-Type-Options "", ""nosniff""); 
      } 
  } 

  • Você pode habilitar o cabeçalho necessário somente para páginas específicas adicionando-o a respostas individuais:
this.Response.Headers[""X-Content-Type-Options""] = ""nosniff""; 

Proteger ou desativar a resolução de entidade XML

Cargo Detalhes
Componente Aplicação Web
Fase SDL Criar
Tecnologias aplicáveis Genérico
Atributos N/A
Referências Expansão de entidade XML, Ataques e defesas de negação de serviço XML, Visão geral de segurança do MSXML, práticas recomendadas para proteger o código MSXML, referência do protocolo NSXMLParserDelegate, resolução de referências externas
Passos

Embora não seja amplamente utilizado, há um recurso do XML que permite que o analisador XML expanda entidades de macro com valores definidos dentro do próprio documento ou de fontes externas. Por exemplo, o documento pode definir uma entidade "companyname" com o valor "Microsoft", de modo que sempre que o texto "&companyname;" aparecer no documento, ele seja automaticamente substituído pelo texto Microsoft. Ou, o documento pode definir uma entidade "MSFTStock" que faz referência a um serviço Web externo para buscar o valor atual do estoque da Microsoft.

Em seguida, sempre que "&MSFTStock;" aparece no documento, ele é automaticamente substituído pelo preço atual das ações. No entanto, essa funcionalidade pode ser abusada para criar condições de negação de serviço (DoS). Um invasor pode aninhar várias entidades para criar uma bomba XML de expansão exponencial que consome toda a memória disponível no sistema.

Como alternativa, ele pode criar uma referência externa que transmite uma quantidade infinita de dados ou que simplesmente trava o thread. Como resultado, todas as equipes devem desabilitar totalmente a resolução de entidade XML interna e/ou externa se seu aplicativo não usá-la, ou limitar manualmente a quantidade de memória e o tempo que o aplicativo pode consumir para a resolução da entidade, se essa funcionalidade for absolutamente necessária. Se a resolução de entidade não for exigida pelo seu aplicativo, desative-a.

Exemplo

Para o código do .NET Framework, você pode usar as seguintes abordagens:

XmlTextReader reader = new XmlTextReader(stream);
reader.ProhibitDtd = true;

XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = true;
XmlReader reader = XmlReader.Create(stream, settings);

// for .NET 4
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Prohibit;
XmlReader reader = XmlReader.Create(stream, settings);

Observe que o valor padrão de ProhibitDtd in é true, mas in XmlTextReader XmlReaderSettings é false. Se você estiver usando XmlReaderSettings, você não precisa definir ProhibitDtd como true explicitamente, mas é recomendado por uma questão de segurança que você faça. Observe também que a classe XmlDocument permite a resolução de entidade por padrão.

Exemplo

Para desabilitar a resolução de entidade para XmlDocuments, use a sobrecarga do método Load e defina as propriedades apropriadas no argumento XmlReader para desabilitar a resolução, conforme ilustrado no código a XmlDocument.Load(XmlReader) seguir:

XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = true;
XmlReader reader = XmlReader.Create(stream, settings);
XmlDocument doc = new XmlDocument();
doc.Load(reader);

Exemplo

Se a desativação da resolução de entidade não for possível para seu aplicativo, defina a propriedade XmlReaderSettings.MaxCharactersFromEntities para um valor razoável de acordo com as necessidades do seu aplicativo. Isso limitará o impacto de potenciais ataques DoS de expansão exponencial. O código a seguir fornece um exemplo dessa abordagem:

XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = false;
settings.MaxCharactersFromEntities = 1000;
XmlReader reader = XmlReader.Create(stream, settings);

Exemplo

Se você precisar resolver entidades embutidas, mas não precisar resolver entidades externas, defina a propriedade XmlReaderSettings.XmlResolver como null. Por exemplo:

XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = false;
settings.MaxCharactersFromEntities = 1000;
settings.XmlResolver = null;
XmlReader reader = XmlReader.Create(stream, settings);

Observe que no MSXML6, ProhibitDTD é definido como true (desabilitando o processamento DTD) por padrão. Para o código Apple OSX/iOS, há dois analisadores XML que você pode usar: NSXMLParser e libXML2.

Aplicativos que utilizam http.sys executam verificação de canonicalização de URL

Cargo Detalhes
Componente Aplicação Web
Fase SDL Criar
Tecnologias aplicáveis Genérico
Atributos N/A
Referências N/A
Passos

Qualquer aplicativo que use http.sys deve seguir estas diretrizes:

  • Limite o comprimento da URL a não mais de 16.384 caracteres (ASCII ou Unicode). Este é o comprimento máximo absoluto da URL com base na configuração padrão do IIS (Serviços de Informações da Internet) 6. Os sítios Web devem esforçar-se por obter um comprimento mais curto do que este, se possível
  • Use as classes de E/S de arquivo padrão do .NET Framework (como FileStream), pois elas aproveitarão as regras de canonicalização no .NET FX
  • Criar explicitamente uma lista de permissões de nomes de arquivos conhecidos
  • Rejeite explicitamente tipos de arquivos conhecidos que você não servirá UrlScan rejeita: exe, bat, cmd, com, htw, ida, idq, htr, idc, shtm[l], stm, printer, ini, pol, dat files
  • Pegue as seguintes exceções:
    • System.ArgumentException (para nomes de dispositivos)
    • System.NotSupportedException (para fluxos de dados)
    • System.IO.FileNotFoundException (para nomes de arquivos com escape inválidos)
    • System.IO.DirectoryNotFoundException (para dirs com escape inválido)
  • Não chame APIs de E/S de arquivo Win32. Em um URL inválido, retorne normalmente um erro 400 para o usuário e registre o erro real.

Certifique-se de que os controles apropriados estejam em vigor ao aceitar arquivos de usuários

Cargo Detalhes
Componente Aplicação Web
Fase SDL Criar
Tecnologias aplicáveis Genérico
Atributos N/A
Referências Carregamento irrestrito de ficheiros, Tabela de assinaturas de ficheiros
Passos

Os ficheiros carregados representam um risco significativo para as aplicações.

O primeiro passo em muitos ataques é obter algum código para o sistema a ser atacado. Em seguida, o ataque só precisa encontrar uma maneira de executar o código. Usar um upload de arquivo ajuda o invasor a realizar a primeira etapa. As consequências do upload irrestrito de arquivos podem variar, incluindo a aquisição completa do sistema, um sistema de arquivos ou banco de dados sobrecarregado, ataques de encaminhamento para sistemas back-end e desfiguração simples.

Depende do que o aplicativo faz com o arquivo carregado e, especialmente, onde ele está armazenado. A validação do lado do servidor dos carregamentos de ficheiros está em falta. Os seguintes controlos de segurança devem ser implementados para a funcionalidade de Carregamento de Ficheiros:

  • Verificação da extensão de arquivo (somente um conjunto válido de tipo de arquivo permitido deve ser aceito)
  • Limite máximo de tamanho de ficheiro
  • O arquivo não deve ser carregado para webroot; o local deve ser um diretório na unidade que não é do sistema
  • A convenção de nomenclatura deve ser seguida, de modo que o nome do arquivo carregado tenha alguma aleatoriedade, de modo a evitar substituições de arquivos
  • Os arquivos devem ser verificados em busca de antivírus antes de gravar no disco
  • Verifique se o nome do arquivo e quaisquer outros metadados (por exemplo, caminho do arquivo) estão validados para caracteres mal-intencionados
  • A assinatura do formato de arquivo deve ser verificada, para impedir que um usuário carregue um arquivo mascarado (por exemplo, carregando um arquivo exe alterando a extensão para txt)

Exemplo

Para obter o último ponto sobre a validação de assinatura de formato de arquivo, consulte a classe abaixo para obter detalhes:

        private static Dictionary<string, List<byte[]>> fileSignature = new Dictionary<string, List<byte[]>>
                    {
                    { ".DOC", new List<byte[]> { new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 } } },
                    { ".DOCX", new List<byte[]> { new byte[] { 0x50, 0x4B, 0x03, 0x04 } } },
                    { ".PDF", new List<byte[]> { new byte[] { 0x25, 0x50, 0x44, 0x46 } } },
                    { ".ZIP", new List<byte[]> 
                                            {
                                              new byte[] { 0x50, 0x4B, 0x03, 0x04 },
                                              new byte[] { 0x50, 0x4B, 0x4C, 0x49, 0x54, 0x55 },
                                              new byte[] { 0x50, 0x4B, 0x53, 0x70, 0x58 },
                                              new byte[] { 0x50, 0x4B, 0x05, 0x06 },
                                              new byte[] { 0x50, 0x4B, 0x07, 0x08 },
                                              new byte[] { 0x57, 0x69, 0x6E, 0x5A, 0x69, 0x70 }
                                                }
                                            },
                    { ".PNG", new List<byte[]> { new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A } } },
                    { ".JPG", new List<byte[]>
                                    {
                                              new byte[] { 0xFF, 0xD8, 0xFF, 0xE0 },
                                              new byte[] { 0xFF, 0xD8, 0xFF, 0xE1 },
                                              new byte[] { 0xFF, 0xD8, 0xFF, 0xE8 }
                                    }
                                    },
                    { ".JPEG", new List<byte[]>
                                        { 
                                            new byte[] { 0xFF, 0xD8, 0xFF, 0xE0 },
                                            new byte[] { 0xFF, 0xD8, 0xFF, 0xE2 },
                                            new byte[] { 0xFF, 0xD8, 0xFF, 0xE3 }
                                        }
                                        },
                    { ".XLS", new List<byte[]>
                                            {
                                              new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 },
                                              new byte[] { 0x09, 0x08, 0x10, 0x00, 0x00, 0x06, 0x05, 0x00 },
                                              new byte[] { 0xFD, 0xFF, 0xFF, 0xFF }
                                            }
                                            },
                    { ".XLSX", new List<byte[]> { new byte[] { 0x50, 0x4B, 0x03, 0x04 } } },
                    { ".GIF", new List<byte[]> { new byte[] { 0x47, 0x49, 0x46, 0x38 } } }
                };

        public static bool IsValidFileExtension(string fileName, byte[] fileData, byte[] allowedChars)
        {
            if (string.IsNullOrEmpty(fileName) || fileData == null || fileData.Length == 0)
            {
                return false;
            }

            bool flag = false;
            string ext = Path.GetExtension(fileName);
            if (string.IsNullOrEmpty(ext))
            {
                return false;
            }

            ext = ext.ToUpperInvariant();

            if (ext.Equals(".TXT") || ext.Equals(".CSV") || ext.Equals(".PRN"))
            {
                foreach (byte b in fileData)
                {
                    if (b > 0x7F)
                    {
                        if (allowedChars != null)
                        {
                            if (!allowedChars.Contains(b))
                            {
                                return false;
                            }
                        }
                        else
                        {
                            return false;
                        }
                    }
                }

                return true;
            }

            if (!fileSignature.ContainsKey(ext))
            {
                return true;
            }

            List<byte[]> sig = fileSignature[ext];
            foreach (byte[] b in sig)
            {
                var curFileSig = new byte[b.Length];
                Array.Copy(fileData, curFileSig, b.Length);
                if (curFileSig.SequenceEqual(b))
                {
                    flag = true;
                    break;
                }
            }

            return flag;
        }

Certifique-se de que os parâmetros de segurança de tipo sejam usados no Aplicativo Web para acesso a dados

Cargo Detalhes
Componente Aplicação Web
Fase SDL Criar
Tecnologias aplicáveis Genérico
Atributos N/A
Referências N/A
Passos

Se você usar a coleção Parameters, o SQL tratará a entrada como um valor literal em vez de como código executável. A coleção Parameters pode ser usada para impor restrições de tipo e comprimento nos dados de entrada. Valores fora do intervalo acionam uma exceção. Se os parâmetros SQL seguros para tipos não forem usados, os invasores poderão executar ataques de injeção incorporados na entrada não filtrada.

Use parâmetros seguros de tipo ao construir consultas SQL para evitar possíveis ataques de injeção de SQL que podem ocorrer com entrada não filtrada. Você pode usar parâmetros seguros de tipo com procedimentos armazenados e com instruções SQL dinâmicas. Os parâmetros são tratados como valores literais pelo banco de dados e não como código executável. Os parâmetros também são verificados quanto ao tipo e comprimento.

Exemplo

O código a seguir mostra como usar parâmetros seguros de tipo com o SqlParameterCollection ao chamar um procedimento armazenado.

using System.Data;
using System.Data.SqlClient;

using (SqlConnection connection = new SqlConnection(connectionString))
{ 
DataSet userDataset = new DataSet(); 
SqlDataAdapter myCommand = new SqlDataAdapter("LoginStoredProcedure", connection); 
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure; 
myCommand.SelectCommand.Parameters.Add("@au_id", SqlDbType.VarChar, 11); 
myCommand.SelectCommand.Parameters["@au_id"].Value = SSN.Text; 
myCommand.Fill(userDataset);
}  

No exemplo de código anterior, o valor de entrada não pode ser maior do que 11 caracteres. Se os dados não estiverem em conformidade com o tipo ou comprimento definido pelo parâmetro, a classe SqlParameter lançará uma exceção.

Use classes de vinculação de modelo separadas ou listas de filtros de vinculação para evitar a vulnerabilidade de atribuição em massa do MVC

Cargo Detalhes
Componente Aplicação Web
Fase SDL Criar
Tecnologias aplicáveis MVC5, MVC6
Atributos N/A
Referências Atributos de metadados, Vulnerabilidade e mitigação de segurança de chave pública, Guia completo para atribuição em massa no MVC ASP.NET, Introdução ao EF usando MVC
Passos
  • Quando devo procurar vulnerabilidades de sobrepostagem? - Vulnerabilidades de sobrepostagem podem ocorrer em qualquer lugar em que você vincule classes de modelo da entrada do usuário. Estruturas como MVC podem representar dados do usuário em classes .NET personalizadas, incluindo POCOs (Plain Old CLR Objects). O MVC preenche automaticamente essas classes de modelo com dados da solicitação, fornecendo uma representação conveniente para lidar com a entrada do usuário. Quando essas classes incluem propriedades que não devem ser definidas pelo usuário, o aplicativo pode ser vulnerável a ataques de postagem excessiva, que permitem o controle do usuário de dados que o aplicativo nunca pretendeu. Como a vinculação de modelo MVC, as tecnologias de acesso ao banco de dados, como mapeadores objeto/relacionais, como o Entity Framework, muitas vezes também suportam o uso de objetos POCO para representar dados de banco de dados. Essas classes de modelo de dados fornecem a mesma conveniência ao lidar com dados de banco de dados que o MVC faz ao lidar com a entrada do usuário. Como o MVC e o banco de dados suportam modelos semelhantes, como objetos POCO, parece fácil reutilizar as mesmas classes para ambos os fins. Essa prática não consegue preservar a separação de preocupações, e é uma área comum em que propriedades não intencionais são expostas à vinculação de modelo, permitindo ataques de postagem excessiva.
  • Por que não devo usar minhas classes de modelo de banco de dados não filtradas como parâmetros para minhas ações MVC? - Porque a vinculação de modelo MVC vinculará qualquer coisa nessa classe. Mesmo que os dados não apareçam em sua exibição, um usuário mal-intencionado pode enviar uma solicitação HTTP com esses dados incluídos, e o MVC terá prazer em vinculá-los porque sua ação diz que a classe de banco de dados é a forma de dados que deve aceitar para entrada do usuário.
  • Por que devo me preocupar com a forma usada para a vinculação do modelo? - Usar ASP.NET vinculação de modelo MVC com modelos excessivamente amplos expõe um aplicativo a ataques de postagem excessiva. O excesso de postagem pode permitir que os invasores alterem os dados do aplicativo além do que o desenvolvedor pretendia, como substituir o preço de um item ou os privilégios de segurança de uma conta. Os aplicativos devem usar modelos de vinculação específicos de ação (ou listas de filtros de propriedades permitidas específicas) para fornecer um contrato explícito para o que a entrada não confiável permitir por meio da vinculação de modelo.
  • Ter modelos de vinculação separados é apenas duplicar o código? - Não, é uma questão de separação de preocupações. Se você reutilizar modelos de banco de dados em métodos de ação, estará dizendo que qualquer propriedade (ou subpropriedade) nessa classe pode ser definida pelo usuário em uma solicitação HTTP. Se não for isso que você deseja que o MVC faça, você precisará de uma lista de filtros ou uma forma de classe separada para mostrar ao MVC quais dados podem vir da entrada do usuário.
  • Se eu tiver modelos de vinculação separados para entrada do usuário, terei que duplicar todos os meus atributos de anotação de dados? - Não necessariamente. Você pode usar MetadataTypeAttribute na classe de modelo de banco de dados para vincular aos metadados em uma classe de vinculação de modelo. Observe apenas que o tipo referenciado pelo MetadataTypeAttribute deve ser um subconjunto do tipo de referência (ele pode ter menos propriedades, mas não mais).
  • Mover dados de um lado para o outro entre modelos de entrada do usuário e modelos de banco de dados é tedioso. Posso simplesmente copiar todas as propriedades usando reflexão? - Sim. As únicas propriedades que aparecem nos modelos de vinculação são aquelas que você determinou serem seguras para entrada do usuário. Não há nenhum motivo de segurança que impeça o uso da reflexão para copiar todas as propriedades que existem em comum entre esses dois modelos.
  • E quanto a [Bind(Exclude ="…")]. Posso usá-lo em vez de ter modelos de vinculação separados? - Esta abordagem não é recomendada. Usar [Bind(Exclude ="…")] significa que qualquer nova propriedade é vinculável por padrão. Quando uma nova propriedade é adicionada, há uma etapa extra para se lembrar de manter as coisas seguras, em vez de ter o design seguro por padrão. Dependendo do incorporador, verificar essa lista toda vez que um imóvel é adicionado é arriscado.
  • [Bind(Include ="…")] é útil para operações de edição? - Não [Bind(Include ="…")] só é adequado para operações no estilo INSERT (adicionando novos dados). Para operações no estilo UPDATE (revisão de dados existentes), use outra abordagem, como ter modelos de vinculação separados ou passar uma lista explícita de propriedades permitidas para UpdateModel ou TryUpdateModel. Adicionar um atributo [Bind(Include ="…")] em uma operação Edit significa que o MVC criará uma instância de objeto e definirá apenas as propriedades listadas, deixando todas as outras em seus valores padrão. Quando os dados forem persistentes, eles substituirão totalmente a entidade existente, redefinindo os valores de quaisquer propriedades omitidas para seus padrões. Por exemplo, se IsAdmin fosse omitido de um atributo [Bind(Include ="…")] em uma operação Editar, qualquer usuário cujo nome fosse editado por meio dessa ação seria redefinido para IsAdmin = false (qualquer usuário editado perderia o status de administrador). Se você quiser impedir atualizações em determinadas propriedades, use uma das outras abordagens acima. Observe que algumas versões das ferramentas MVC geram classes de controlador com [Bind(Include ="…")] em Editar ações e implicam que remover uma propriedade dessa lista evitará ataques de postagem excessiva. No entanto, conforme descrito acima, essa abordagem não funciona como pretendido e, em vez disso, redefinirá todos os dados nas propriedades omitidas para seus valores padrão.
  • Para operações Create, há alguma advertência usando [Bind(Include ="…")] em vez de modelos de vinculação separados? - Sim. Primeiro, essa abordagem não funciona para cenários de edição, exigindo a manutenção de duas abordagens separadas para mitigar todas as vulnerabilidades de sobrepostagem. Em segundo lugar, modelos de vinculação separados impõem a separação de preocupações entre a forma usada para entrada do usuário e a forma usada para persistência, algo que [Bind(Include ="…")] não faz. Em terceiro lugar, observe que [Bind(Include ="…")] só pode lidar com propriedades de nível superior; Não é possível permitir apenas partes de subpropriedades (como "Details.Name") no atributo. Finalmente, e talvez o mais importante, usar [Bind(Include ="…")] adiciona uma etapa extra que deve ser lembrada sempre que a classe for usada para vinculação de modelo. Se um novo método de ação se ligar diretamente à classe de dados e esquecer de incluir um atributo [Bind(Include ="…")], ele poderá ficar vulnerável a ataques de sobrepostagem, de modo que a abordagem [Bind(Include ="…")] será um pouco menos segura por padrão. Se você usar [Bind(Include ="…")], lembre-se sempre de especificá-lo sempre que suas classes de dados aparecerem como parâmetros de método de ação.
  • Para operações Create, que tal colocar o atributo [Bind(Include ="…")] na própria classe do modelo? Essa abordagem não evita a necessidade de lembrar de colocar o atributo em cada método de ação? - Esta abordagem funciona em alguns casos. Usar [Bind(Include ="…")] no próprio tipo de modelo (em vez de nos parâmetros de ação usando essa classe), evita a necessidade de lembrar de incluir o atributo [Bind(Include ="…")] em cada método de ação. O uso do atributo diretamente na classe cria efetivamente uma área de superfície separada dessa classe para fins de vinculação de modelo. No entanto, essa abordagem permite apenas uma forma de vinculação de modelo por classe de modelo. Se um método de ação precisar permitir a vinculação de modelo de um campo (por exemplo, uma ação somente de administrador que atualiza funções de usuário) e outras ações precisarem impedir a vinculação de modelo desse campo, essa abordagem não funcionará. Cada classe só pode ter uma forma de vinculação de modelo; se diferentes ações precisarem de formas de vinculação de modelo diferentes, elas precisarão representar essas formas separadas usando classes de vinculação de modelo separadas ou atributos [Bind(Include ="…")] separados nos métodos de ação.
  • O que são modelos de ligação? São a mesma coisa que modelos de visualização? - Trata-se de dois conceitos relacionados. O termo modelo de vinculação refere-se a uma classe de modelo usada na lista de parâmetros de uma ação (a forma passada da vinculação do modelo MVC para o método action). O termo modelo de exibição refere-se a uma classe de modelo passada de um método de ação para um modo de exibição. O uso de um modelo específico de exibição é uma abordagem comum para passar dados de um método de ação para um modo de exibição. Muitas vezes, essa forma também é adequada para vinculação de modelo, e o termo modelo de exibição pode ser usado para se referir ao mesmo modelo usado em ambos os lugares. Para ser mais preciso, este procedimento fala especificamente sobre modelos de ligação, focando na forma passada para a ação, que é o que importa para fins de atribuição em massa.

Codifique saídas da Web não confiáveis antes da renderização

Cargo Detalhes
Componente Aplicação Web
Fase SDL Criar
Tecnologias aplicáveis Genérico, Web Forms, MVC5, MVC6
Atributos N/A
Referências Como evitar scripts entre sites no ASP.NET, Scripts entre sites, XSS (Cross Site Scripting) Prevenção Cheat Sheet
Passos O script entre sites (comumente abreviado como XSS) é um vetor de ataque para serviços online ou qualquer aplicativo/componente que consome entrada da Web. As vulnerabilidades XSS podem permitir que um invasor execute scripts na máquina de outro usuário por meio de um aplicativo Web vulnerável. Scripts maliciosos podem ser usados para roubar cookies e, de outra forma, adulterar a máquina de uma vítima através de JavaScript. O XSS é impedido validando a entrada do usuário, garantindo que ela esteja bem formada e codificando antes de ser processada em uma página da Web. A validação de entrada e a codificação de saída podem ser feitas usando a Biblioteca de Proteção da Web. Para código gerenciado (C#, VB.NET, etc.), use um ou mais métodos de codificação apropriados da Biblioteca de Proteção da Web (Anti-XSS), dependendo do contexto em que a entrada do usuário é manifestada:

Exemplo

* Encoder.HtmlEncode 
* Encoder.HtmlAttributeEncode 
* Encoder.JavaScriptEncode 
* Encoder.UrlEncode
* Encoder.VisualBasicScriptEncode 
* Encoder.XmlEncode 
* Encoder.XmlAttributeEncode 
* Encoder.CssEncode 
* Encoder.LdapEncode 

Executar validação de entrada e filtragem em todas as propriedades do modelo de tipo de cadeia de caracteres

Cargo Detalhes
Componente Aplicação Web
Fase SDL Criar
Tecnologias aplicáveis Genérico, MVC5, MVC6
Atributos N/A
Referências Adicionando validação, validando dados de modelo em um aplicativo MVC, princípios orientadores para seus aplicativos MVC ASP.NET
Passos

Todos os parâmetros de entrada devem ser validados antes de serem usados no aplicativo para garantir que o aplicativo seja protegido contra entradas de usuários mal-intencionados. Valide os valores de entrada usando validações de expressão regular no lado do servidor com uma estratégia de validação de lista permitida. Entradas/parâmetros de usuário não higienizados passados para os métodos podem causar vulnerabilidades de injeção de código.

Para aplicativos Web, os pontos de entrada também podem incluir campos de formulário, QueryStrings, cookies, cabeçalhos HTTP e parâmetros de serviço Web.

As seguintes verificações de validação de entrada devem ser realizadas após a vinculação do modelo:

  • As propriedades do modelo devem ser anotadas com anotação RegularExpression, para aceitar caracteres permitidos e comprimento máximo permitido
  • Os métodos do controlador devem executar a validade ModelState

A higienização deve ser aplicada em campos de formulário que aceitam todos os caracteres, por exemplo, editor de rich text

Cargo Detalhes
Componente Aplicação Web
Fase SDL Criar
Tecnologias aplicáveis Genérico
Atributos N/A
Referências Codificar entrada não segura, HTML Sanitizer
Passos

Identifique todas as marcas de marcação estáticas que você deseja usar. Uma prática comum é restringir a formatação a elementos HTML seguros, como <b> (negrito) e <i> (itálico).

Antes de gravar os dados, codifice-os HTML. Isso torna qualquer script mal-intencionado seguro, fazendo com que ele seja tratado como texto, não como código executável.

  1. Desative ASP.NET validação de solicitação adicionando o atributo ValidateRequest="false" à diretiva @ Page
  2. Codifique a entrada de cadeia de caracteres com o método HtmlEncode
  3. Use um StringBuilder e chame seu método Replace para remover seletivamente a codificação nos elementos HTML que você deseja permitir

A página nas referências desativa ASP.NET validação de solicitação definindo ValidateRequest="false". Ele codifica a entrada em HTML e permite seletivamente que uma <b> <i> biblioteca .NET para limpeza HTML também possa ser usada.

HtmlSanitizer é uma biblioteca .NET para limpar fragmentos HTML e documentos de construções que podem levar a ataques XSS. Ele usa o AngleSharp para analisar, manipular e renderizar HTML e CSS. O HtmlSanitizer pode ser instalado como um pacote NuGet, e a entrada do usuário pode ser passada através de métodos de limpeza HTML ou CSS relevantes, conforme aplicável, no lado do servidor. Por favor, note que a higienização como um controle de segurança deve ser considerada apenas como uma última opção.

A validação de entrada e a codificação de saída são consideradas melhores controles de segurança.

Não atribua elementos DOM a coletores que não tenham codificação incorporada

Cargo Detalhes
Componente Aplicação Web
Fase SDL Criar
Tecnologias aplicáveis Genérico
Atributos N/A
Referências N/A
Passos Muitas funções JavaScript não fazem codificação por padrão. Ao atribuir entrada não confiável a elementos DOM por meio de tais funções, pode resultar em execuções de script entre sites (XSS).

Exemplo

Seguem-se exemplos inseguros:

document.getElementByID("div1").innerHtml = value;
$("#userName").html(res.Name);
return $('<div/>').html(value)
$('body').append(resHTML);   

Não use, em vez disso, use innerHtmlinnerText. Da mesma forma, em vez de $("#elm").html(), use $("#elm").text()

Valide se todos os redirecionamentos dentro do aplicativo estão fechados ou feitos com segurança

Cargo Detalhes
Componente Aplicação Web
Fase SDL Criar
Tecnologias aplicáveis Genérico
Atributos N/A
Referências A estrutura de autorização do OAuth 2.0 - Redirecionadores abertos
Passos

O design do aplicativo que requer redirecionamento para um local fornecido pelo usuário deve restringir os possíveis destinos de redirecionamento a uma lista "segura" predefinida de sites ou domínios. Todos os redirecionamentos no aplicativo devem ser fechados/seguros.

Para:

  • Identificar todos os redirecionamentos
  • Implemente uma mitigação apropriada para cada redirecionamento. As atenuações apropriadas incluem redirecionar a lista permitida ou a confirmação do usuário. Se um site ou serviço com uma vulnerabilidade de redirecionamento aberta usar provedores de identidade Facebook/OAuth/OpenID, um invasor poderá roubar o token de logon de um usuário e se passar por esse usuário. Este é um risco inerente ao usar o OAuth, que está documentado no RFC 6749 "The OAuth 2.0 Authorization Framework", Seção 10.15 "Open Redirects" Da mesma forma, as credenciais dos usuários podem ser comprometidas por ataques de spear phishing usando redirecionamentos abertos

Implementar validação de entrada em todos os parâmetros de tipo de cadeia de caracteres aceitos pelos métodos Controller

Cargo Detalhes
Componente Aplicação Web
Fase SDL Criar
Tecnologias aplicáveis Genérico, MVC5, MVC6
Atributos N/A
Referências Validando dados de modelo em um aplicativo MVC, princípios orientadores para seus aplicativos MVC ASP.NET
Passos Para métodos que aceitam apenas o tipo de dados primitivo, e não modelos como argumento, a validação de entrada usando Expressão Regular deve ser feita. Aqui Regex.IsMatch deve ser usado com um padrão regex válido. Se a entrada não corresponder à Expressão Regular especificada, o controle não deve prosseguir e um aviso adequado sobre falha de validação deve ser exibido.

Definir o tempo limite superior para o processamento de expressões regulares para evitar DoS devido a expressões regulares incorretas

Cargo Detalhes
Componente Aplicação Web
Fase SDL Criar
Tecnologias aplicáveis Genérico, Web Forms, MVC5, MVC6
Atributos N/A
Referências Propriedade DefaultRegexMatchTimeout
Passos Para garantir ataques de negação de serviço contra expressões regulares mal criadas, que causam muitos retrocessos, defina o tempo limite padrão global. Se o tempo de processamento demorar mais do que o limite superior definido, isso lançará uma exceção de tempo limite. Se nada estiver configurado, o tempo limite será infinito.

Exemplo

Por exemplo, a configuração a seguir lançará um RegexMatchTimeoutException, se o processamento demorar mais de 5 segundos:

<httpRuntime targetFramework="4.5" defaultRegexMatchTimeout="00:00:05" />

Evite usar Html.Raw em visualizações do Razor

Cargo Detalhes
Componente Aplicação Web
Fase SDL Criar
Tecnologias aplicáveis MVC5, MVC6
Atributos N/A
Referências N/A
Passo ASP.NET WebPages (Razor) executam codificação HTML automática. Todas as cadeias de caracteres impressas por nuggets de código incorporado (@ blocks) são automaticamente codificadas em HTML. No entanto, quando HtmlHelper.Raw o método é invocado, ele retorna a marcação que não é codificada em HTML. Se Html.Raw() o método auxiliar for usado, ele ignorará a proteção de codificação automática que o Razor fornece.

Exemplo

Segue-se um exemplo inseguro:

<div class="form-group">
            @Html.Raw(Model.AccountConfirmText)
        </div>
        <div class="form-group">
            @Html.Raw(Model.PaymentConfirmText)
        </div>
</div>

Não utilize Html.Raw() a menos que necessite de apresentar marcação. Este método não executa a codificação de saída implicitamente. Use outros auxiliares de ASP.NET, por exemplo, @Html.DisplayFor()

Não use consultas dinâmicas em procedimentos armazenados

Cargo Detalhes
Componente Base de dados
Fase SDL Criar
Tecnologias aplicáveis Genérico
Atributos N/A
Referências N/A
Passos

Um ataque de injeção de SQL explora vulnerabilidades na validação de entrada para executar comandos arbitrários no banco de dados. Isso pode ocorrer quando seu aplicativo usa entrada para construir instruções SQL dinâmicas para acessar o banco de dados. Isso também pode ocorrer se o código usar procedimentos armazenados que são passados cadeias de caracteres que contêm entrada bruta do usuário. Usando o ataque de injeção de SQL, o invasor pode executar comandos arbitrários no banco de dados. Todas as instruções SQL (incluindo as instruções SQL em procedimentos armazenados) devem ser parametrizadas. As instruções SQL parametrizadas aceitarão caracteres que têm significado especial para SQL (como aspas simples) sem problemas porque são fortemente tipados.

Exemplo

Segue-se um exemplo de Procedimento Armazenado dinâmico inseguro:

CREATE PROCEDURE [dbo].[uspGetProductsByCriteria]
(
  @productName nvarchar(200) = NULL,
  @startPrice float = NULL,
  @endPrice float = NULL
)
AS
 BEGIN
  DECLARE @sql nvarchar(max)
  SELECT @sql = ' SELECT ProductID, ProductName, Description, UnitPrice, ImagePath' +
       ' FROM dbo.Products WHERE 1 = 1 '
       PRINT @sql
  IF @productName IS NOT NULL
     SELECT @sql = @sql + ' AND ProductName LIKE ''%' + @productName + '%'''
  IF @startPrice IS NOT NULL
     SELECT @sql = @sql + ' AND UnitPrice > ''' + CONVERT(VARCHAR(10),@startPrice) + ''''
  IF @endPrice IS NOT NULL
     SELECT @sql = @sql + ' AND UnitPrice < ''' + CONVERT(VARCHAR(10),@endPrice) + ''''

  PRINT @sql
  EXEC(@sql)
 END

Exemplo

A seguir está o mesmo procedimento armazenado implementado com segurança:

CREATE PROCEDURE [dbo].[uspGetProductsByCriteriaSecure]
(
             @productName nvarchar(200) = NULL,
             @startPrice float = NULL,
             @endPrice float = NULL
)
AS
       BEGIN
             SELECT ProductID, ProductName, Description, UnitPrice, ImagePath
             FROM dbo.Products where
             (@productName IS NULL or ProductName like '%'+ @productName +'%')
             AND
             (@startPrice IS NULL or UnitPrice > @startPrice)
             AND
             (@endPrice IS NULL or UnitPrice < @endPrice)         
       END

Certifique-se de que a validação do modelo seja feita em métodos de API da Web

Cargo Detalhes
Componente API da Web
Fase SDL Criar
Tecnologias aplicáveis MVC5, MVC6
Atributos N/A
Referências Validação de modelo em ASP.NET API Web
Passos Quando um cliente envia dados para uma API da Web, é obrigatório validar os dados antes de fazer qualquer processamento. Para ASP.NET APIs da Web que aceitam modelos como entrada, use anotações de dados em modelos para definir regras de validação nas propriedades do modelo.

Exemplo

O código a seguir demonstra o mesmo:

using System.ComponentModel.DataAnnotations;

namespace MyApi.Models
{
    public class Product
    {
        public int Id { get; set; }
        [Required]
        [RegularExpression(@"^[a-zA-Z0-9]*$", ErrorMessage="Only alphanumeric characters are allowed.")]
        public string Name { get; set; }
        public decimal Price { get; set; }
        [Range(0, 999)]
        public double Weight { get; set; }
    }
}

Exemplo

No método de ação dos controladores de API, a validade do modelo deve ser explicitamente verificada, conforme mostrado abaixo:

namespace MyApi.Controllers
{
    public class ProductsController : ApiController
    {
        public HttpResponseMessage Post(Product product)
        {
            if (ModelState.IsValid)
            {
                // Do something with the product (not shown).

                return new HttpResponseMessage(HttpStatusCode.OK);
            }
            else
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }
        }
    }
}

Implementar a validação de entrada em todos os parâmetros de tipo de cadeia de caracteres aceitos pelos métodos da API da Web

Cargo Detalhes
Componente API da Web
Fase SDL Criar
Tecnologias aplicáveis Genérico, MVC 5, MVC 6
Atributos N/A
Referências Validando dados de modelo em um aplicativo MVC, princípios orientadores para seus aplicativos MVC ASP.NET
Passos Para métodos que aceitam apenas o tipo de dados primitivo, e não modelos como argumento, a validação de entrada usando Expressão Regular deve ser feita. Aqui Regex.IsMatch deve ser usado com um padrão regex válido. Se a entrada não corresponder à Expressão Regular especificada, o controle não deve prosseguir e um aviso adequado sobre falha de validação deve ser exibido.

Certifique-se de que os parâmetros de segurança de tipo sejam usados na API da Web para acesso a dados

Cargo Detalhes
Componente API da Web
Fase SDL Criar
Tecnologias aplicáveis Genérico
Atributos N/A
Referências N/A
Passos

Se você usar a coleção Parameters, o SQL tratará a entrada como um valor literal em vez de como código executável. A coleção Parameters pode ser usada para impor restrições de tipo e comprimento nos dados de entrada. Valores fora do intervalo acionam uma exceção. Se os parâmetros SQL seguros para tipos não forem usados, os invasores poderão executar ataques de injeção incorporados na entrada não filtrada.

Use parâmetros seguros de tipo ao construir consultas SQL para evitar possíveis ataques de injeção de SQL que podem ocorrer com entrada não filtrada. Você pode usar parâmetros seguros de tipo com procedimentos armazenados e com instruções SQL dinâmicas. Os parâmetros são tratados como valores literais pelo banco de dados e não como código executável. Os parâmetros também são verificados quanto ao tipo e comprimento.

Exemplo

O código a seguir mostra como usar parâmetros seguros de tipo com o SqlParameterCollection ao chamar um procedimento armazenado.

using System.Data;
using System.Data.SqlClient;

using (SqlConnection connection = new SqlConnection(connectionString))
{ 
DataSet userDataset = new DataSet(); 
SqlDataAdapter myCommand = new SqlDataAdapter("LoginStoredProcedure", connection); 
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure; 
myCommand.SelectCommand.Parameters.Add("@au_id", SqlDbType.VarChar, 11); 
myCommand.SelectCommand.Parameters["@au_id"].Value = SSN.Text; 
myCommand.Fill(userDataset);
}  

No exemplo de código anterior, o valor de entrada não pode ser maior do que 11 caracteres. Se os dados não estiverem em conformidade com o tipo ou comprimento definido pelo parâmetro, a classe SqlParameter lançará uma exceção.

Usar consultas SQL parametrizadas para o Azure Cosmos DB

Cargo Detalhes
Componente Banco de Dados de Documentos do Azure
Fase SDL Criar
Tecnologias aplicáveis Genérico
Atributos N/A
Referências Anunciando a parametrização SQL no Azure Cosmos DB
Passos Embora o Azure Cosmos DB ofereça suporte apenas a consultas somente leitura, a injeção de SQL ainda é possível se as consultas forem construídas concatenando com a entrada do usuário. Pode ser possível que um usuário obtenha acesso a dados que não deveria estar acessando dentro da mesma coleção criando consultas SQL mal-intencionadas. Use consultas SQL parametrizadas se as consultas forem construídas com base na entrada do usuário.

Validação de entrada do WCF por meio da vinculação de esquema

Cargo Detalhes
Componente WCF
Fase SDL Criar
Tecnologias aplicáveis Genérico, NET Framework 3
Atributos N/A
Referências MSDN
Passos

A falta de validação leva a diferentes tipos de ataques de injeção.

A validação de mensagem representa uma linha de defesa na proteção do seu aplicativo WCF. Com essa abordagem, você valida mensagens usando esquemas para proteger as operações do serviço WCF contra ataques de um cliente mal-intencionado. Valide todas as mensagens recebidas pelo cliente para protegê-lo de ataques de um serviço mal-intencionado. A validação de mensagens torna possível validar mensagens quando as operações consomem contratos de mensagens ou contratos de dados, o que não pode ser feito usando validação de parâmetros. A validação de mensagens permite criar lógica de validação dentro de esquemas, proporcionando mais flexibilidade e reduzindo o tempo de desenvolvimento. Os esquemas podem ser reutilizados em diferentes aplicativos dentro da organização, criando padrões para representação de dados. Além disso, a validação de mensagens permite proteger as operações quando elas consomem tipos de dados mais complexos envolvendo contratos que representam a lógica de negócios.

Para executar a validação de mensagens, primeiro crie um esquema que represente as operações do seu serviço e os tipos de dados consumidos por essas operações. Em seguida, você cria uma classe .NET que implementa um inspetor de mensagens de cliente personalizado e um inspetor de mensagens de despachante personalizado para validar as mensagens enviadas/recebidas de/para o serviço. Em seguida, implemente um comportamento de ponto de extremidade personalizado para habilitar a validação de mensagens no cliente e no serviço. Finalmente, você implementa um elemento de configuração personalizado na classe que permite expor o comportamento do ponto de extremidade personalizado estendido no arquivo de configuração do serviço ou do cliente"

WCF- Validação de entrada através de inspetores de parâmetros

Cargo Detalhes
Componente WCF
Fase SDL Criar
Tecnologias aplicáveis Genérico, NET Framework 3
Atributos N/A
Referências MSDN
Passos

A validação de entrada e dados representa uma importante linha de defesa na proteção do seu aplicativo WCF. Você deve validar todos os parâmetros expostos nas operações de serviço WCF para proteger o serviço contra ataques de um cliente mal-intencionado. Por outro lado, você também deve validar todos os valores de retorno recebidos pelo cliente para protegê-lo de ataques de um serviço mal-intencionado

O WCF fornece diferentes pontos de extensibilidade que permitem personalizar o comportamento de tempo de execução do WCF criando extensões personalizadas. Os Inspetores de Mensagens e os Inspetores de Parâmetros são dois mecanismos de extensibilidade usados para obter maior controle sobre os dados que passam entre um cliente e um serviço. Você deve usar inspetores de parâmetros para validação de entrada e usar inspetores de mensagens somente quando precisar inspecionar toda a mensagem que entra e sai de um serviço.

Para executar a validação de entrada, você criará uma classe .NET e implementará um inspetor de parâmetros personalizado para validar parâmetros em operações em seu serviço. Em seguida, você implementará um comportamento de ponto de extremidade personalizado para habilitar a validação no cliente e no serviço. Finalmente, você implementará um elemento de configuração personalizado na classe que permite expor o comportamento do ponto de extremidade personalizado estendido no arquivo de configuração do serviço ou do cliente