Share via


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

Produto/Serviço Artigo
Aplicativo Web
Backup de banco de dados
API da Web
Azure DocumentDB
WCF

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

Title Detalhes
Componente Aplicativo Web
Fase do SDL Build
Tecnologias aplicáveis Genérico
Atributos N/D
Referências Segurança do XSLT, Propriedade XsltSettings
Etapas O XSLT dá suporte a scripts em folhas de estilos usando o elemento <msxml:script>. Isso permite que funções personalizadas sejam usadas em uma transformação XSLT. O script é executado no contexto do processo que está realizando a transformação. O script XSLT deve ser desabilitado quando em um ambiente não confiável, para evitar a execução de código não confiável. Se estiver usando o .NET: os scripts XSLT são desabilitados por padrão. No entanto, você deve garantir que eles não sejam explicitamente habilitados por meio da propriedade XsltSettings.EnableScript.

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 XML DOM AllowXsltScript.

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

Exemplo

Se você estiver usando MSXML 5 ou anterior, o script XSLT será habilitado por padrão, e você deverá desabilitá-lo explicitamente. Defina a propriedade de objeto XML DOM AllowXsltScript como false.

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

Verifique se cada página que pode ter conteúdo controlável pelo usuário recusa a detecção automática de MIME

Title Detalhes
Componente Aplicativo Web
Fase do SDL Build
Tecnologias aplicáveis Genérico
Atributos N/D
Referências Segurança do IE8 parte V - proteção abrangente
Etapas

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

Cada tipo de arquivo entregue de um servidor Web tem um tipo MIME (também chamado de tipo de conteúdo) associado 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 seus conteúdos não devem ter o MIME detectado. Esse cabeçalho foi criado para reduzir os ataques de detecção de MIME. Foi adicionado suporte para esse cabeçalho no Internet Explorer 8 (IE8)

Somente os usuários do Internet Explorer 8 (IE8) se beneficiarão de 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) é o único navegador importante a implementar um recurso de recusa de detecção de MIME. Se e quando is principais navegadores (Firefox, Safari, Chrome) implementarem recursos semelhantes, essa recomendação será atualizada para incluir também a sintaxe para esses navegadores

Exemplo

Para habilitar globalmente o cabeçalho necessário para todas as páginas do aplicativo, você tem as seguintes opções:

  • Adicionar o cabeçalho no arquivo web.config se o aplicativo estiver hospedado no Internet Information Services (IIS) 7
<system.webServer> 
  <httpProtocol> 
    <customHeaders> 
      <add name=""X-Content-Type-Options"" value=""nosniff""/>
    </customHeaders>
  </httpProtocol>
</system.webServer> 
  • Adicionar o cabeçalho usando a Aplication_BeginRequest global
void Application_BeginRequest(object sender, EventArgs e)
{
  this.Response.Headers[""X-Content-Type-Options""] = ""nosniff"";
} 
  • Implementar o 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 apenas para páginas específicas adicionando-o a respostas individuais:
this.Response.Headers[""X-Content-Type-Options""] = ""nosniff""; 

Proteger ou desabilitar a resolução de entidade XML

Title Detalhes
Componente Aplicativo Web
Fase do SDL Build
Tecnologias aplicáveis Genérico
Atributos N/D
Referências Expansão de Entidade XML, Ataques de negação de serviço de XML e defesas, Visão geral de segurança do MSXML, Práticas recomendadas para proteger o código do MSXML, Referência de protocolo NSXMLParserDelegate, Resolvendo referências externas
Etapas

Embora não seja amplamente usado, há um recurso XML que permite que o analisador XML expanda entidades de macro com valores definidos no próprio documento ou de fontes externas. Por exemplo, o documento pode definir uma entidade "companyname" com o valor "Microsoft", de modo que toda vez que o texto "&companyname;" aparecer no documento, ele seja automaticamente substituído pelo texto Microsoft. Ou então, o documento pode definir uma entidade "MSFTStock" que faz referência a um serviço Web externo para buscar o valor atual de ações 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 usada para criar condições de DoS (negação de serviço). 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 transmita de volta uma quantidade infinita de dados ou que simplesmente interrompa o thread. Como resultado, todas as equipes deverão desabilitar a resolução de entidade XML interna e/ou externa totalmente se o aplicativo não a usar ou limitar manualmente a quantidade de memória e o tempo que o aplicativo pode consumir para resolução de entidade, se essa funcionalidade for absolutamente necessária. Se a resolução de entidade não for exigida pelo aplicativo, desabilite-a.

Exemplo

Para 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 em XmlReaderSettings é true, mas é false em XmlTextReader. Se estiver usando XmlReaderSettings, você não precisará definir ProhibitDtd como true explicitamente, mas isso é recomendável por razões de seguranç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 o a sobrecarga XmlDocument.Load(XmlReader) do método Load e defina as propriedades adequadas no argumento XmlReader para desabilitar a resolução, conforme ilustrado no seguinte código:

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

Exemplo

Se não for possível para o aplicativo desabilitar a resolução de entidade, defina a propriedade XmlReaderSettings.MaxCharactersFromEntities com um valor razoável, de acordo com as necessidades do aplicativo. Isso limitará o impacto de possíveis ataques de 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 precisar resolver entidades embutidas, mas não precisar resolver entidades externas, defina a propriedade XmlReaderSettings.XmlResolver como nulo. 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 está definido como true (desabilitando o processamento de DTD) por padrão. Para código do Apple OSX/iOS, há dois analisadores XML que você pode usar: NSXMLParser e libXML2.

Os aplicativos que usam http.sys executam a verificação de conversão em formato canônico de URL

Title Detalhes
Componente Aplicativo Web
Fase do SDL Build
Tecnologias aplicáveis Genérico
Atributos N/D
Referências N/D
Etapas

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

  • Limite o comprimento da URL para no máximo 16.384 caracteres (ASCII ou Unicode). Esse é 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 sites devem se esforçar para ter um comprimento menor do que isso, se possível
  • Use as classes de E/S de arquivo padrão do .NET Framework (como FileStream), pois elas tirarão proveito das regras de conversão em formato canônico no .NET FX
  • Criar explicitamente uma lista de permissões de nomes de arquivo conhecidos
  • Rejeite explicitamente tipos de arquivo conhecidos que você não fornecerá a rejeições de UrlScan: exe, bat, cmd, com, htw, ida, idq, htr, idc, shtm[l], stm, printer, ini, pol, arquivos files
  • Utilize as seguintes exceções:
    • System.ArgumentException (para nomes de dispositivo)
    • System.NotSupportedException (para fluxos de dados)
    • System.IO.FileNotFoundException (para nomes com escape inválidos)
    • System.IO.DirectoryNotFoundException (para diretórios com escape inválidos)
  • Não chamar APIs de E/S de arquivo do Win32. Em uma URL inválida, normalmente é retornado um erro 400 para o usuário e o erro real é registrado em log.

Verifique se os controles adequados estão em vigor ao aceitar arquivos de usuários

Title Detalhes
Componente Aplicativo Web
Fase do SDL Build
Tecnologias aplicáveis Genérico
Atributos N/D
Referências Upload de arquivo irrestrito, Tabela de assinatura de arquivo
Etapas

Os arquivos carregados representam um risco significativo para os aplicativos.

A primeira etapa em muitos ataques é obter algum código do sistema a ser atacado. Assim, o ataque só precisa encontrar uma maneira de fazer com que o código seja executado. Usar um upload de arquivo ajuda o invasor a realizar a primeira etapa. As consequências do upload de arquivos irrestrito podem variar, incluindo a tomada de controle completa do sistema, um sistema de arquivos ou banco de dados sobrecarregado, encaminhamento de ataques aos sistemas de back-end e desfiguração simples.

Depende de que o aplicativo faz com o arquivo carregado e, especialmente, onde ele é armazenado. A validação do lado do servidor de uploads de arquivo está ausente. Os controles de segurança a seguir devem ser implementados para a funcionalidade de Upload de Arquivo:

  • Verificação de extensão de arquivo (somente um conjunto válido de tipos de arquivo permitidos deve ser aceito)
  • Limite de tamanho máximo de arquivo
  • O arquivo não deve ser carregado para webroot; o local deve ser um diretório em uma unidade que não seja do sistema
  • A convenção de nomenclatura deve ser seguida, de forma que o nome do arquivo carregado seja aleatório até certo ponto, para impedir que o arquivo seja substituído
  • Os arquivos devem ser verificados com o antivírus antes de serem gravados no disco
  • Verifique se o nome do arquivo e outros metadados (por exemplo, o caminho do arquivo) sã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 o último ponto sobre validação de assinatura de formato de arquivo, confira 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;
        }

Verifique se os parâmetros de tipo seguro são usados no aplicativo Web para acesso a dados

Title Detalhes
Componente Aplicativo Web
Fase do SDL Build
Tecnologias aplicáveis Genérico
Atributos N/D
Referências N/D
Etapas

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

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

Exemplo

O código a seguir mostra como usar parâmetros de tipo seguro com 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 ter mais de 11 caracteres. Se os dados não estão de acordo com o tipo ou o comprimento definido pelo parâmetro, a classe SqlParameter lança uma exceção.

Use classes de model binding separadas ou listas de filtro de associação para evitar a vulnerabilidade de atribuição em massa do MVC

Title Detalhes
Componente Aplicativo Web
Fase do SDL Build
Tecnologias aplicáveis MVC5, MVC6
Atributos N/D
Referências Atributos de metadados, Vulnerabilidade de segurança de chave pública e atenuação, Guia completo para atribuição em massa no ASP.NET MVC, Introdução ao EF usando MVC
Etapas
  • Quando devo procurar vulnerabilidades de excesso de postagem? - As vulnerabilidades de excesso de postagem podem ocorrer em qualquer lugar em que você associa classes de modelo da entrada do usuário. Estruturas como MVC podem representar dados de usuário em classes personalizadas do .NET, incluindo POCOs (Plain Old CLR Objects). O MVC popula automaticamente essas classes de modelo com os 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 overposting, que permitem o controle pelo usuário de dados que o aplicativo nunca deveria permitir. Assim como o model binding MVC, tecnologias de acesso a bancos de dados, como mapeadores de objeto/relacionais como Entity Framework, geralmente também dão suporte ao uso de objetos POCO para representar dados do banco de dados. Essas classes de modelo de dados fornecem a mesma conveniência ao lidar com dados do banco de dados que o MVC oferece ao lidar com a entrada do usuário. Como o MVC e o banco de dados dão suporte a modelos semelhantes, como objetos POCO, parece fácil reutilizar as mesmas classes para as duas finalidades. Essa prática não preservar a separação de questões e é uma área comum em que propriedades não intencionais são expostas ao model binding, habilitando ataques de excesso de postagem.
  • Por que não devo usar minhas classes de modelo de banco de dados não filtradas como parâmetros das ações do MVC? - Porque o model binding do MVC associará tudo nessa classe. Mesmo se os dados não aparecerem no modo de exibição, um usuário mal-intencionado poderá enviar uma solicitação HTTP com esses dados incluídos, e o MVC os associará, pois a ação diz que a classe de banco de dados é a forma de dados que ele deve aceitar para a entrada do usuário.
  • Por que devo me preocupar com a forma usada para model binding? - O uso de model binding do MVC do ASP.NET com modelos muito amplos expõe um aplicativo a ataques de excesso de postagem. O excesso de postagem pode permitir que usuários mal-intencionados alterem dados de aplicativos além do que o desenvolvedor desejava, como substituir o preço de um item ou os privilégios de segurança de uma conta. Os aplicativos devem usar modelos de associação específicos de ação (ou listas de filtros de propriedade permitidos específicos) para fornecer um contrato explícito para quais entradas não confiáveis devem ser permitidas por meio de model binding.
  • Modelos de associação separados apenas duplicam o código? - Não, é uma questão de separação de preocupações. Se reutilizar os modelos de banco de dados nos métodos de ação, você está indicando que qualquer propriedade (ou subpropriedade) nessa classe poderá ser definida pelo usuário em uma solicitação HTTP. Se isso não for o 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 de usuário.
  • Se eu tiver modelos de associação separados para entrada do usuário, preciso duplicar todos os 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 model binding. Apenas observe que o tipo referenciado por MetadataTypeAttribute deve ser um subconjunto do tipo de referência (ele pode ter menos propriedades, mas não mais).
  • A movimentação de dados entre modelos de entrada de usuário e modelos de banco de dados é entediante. Posso simplesmente copiar todas as propriedades usando a reflexão? - Sim. As únicas propriedades que aparecem nos modelos de associação são aquelas que você determinou como seguras para a entrada do usuário. Não há motivo de segurança que impeça o uso de reflexão para copiar todas as propriedades que existem em comum entre esses dois modelos.
  • Que tal [Bind(Exclude ="…")]. Posso usar isso em vez de modelos de associação separados? - Essa abordagem não é recomendada. Usar [Bind(Exclude ="…")] significa que qualquer nova propriedade pode ser associada por padrão. Quando uma nova propriedade é adicionada, há uma etapa extra para se lembrar de manter tudo seguro, em vez de ter o design seguro por padrão. É arriscado depender da verificação dessa lista pelo desenvolvedor sempre que uma propriedade for adicionada.
  • Is [Bind(Include ="…")] é útil para operações de edição? - Não. [Bind(Include ="…")] é adequado apenas para operações do estilo INSERT (adicionar novos dados). Para operações de estilo UPDATE (examinar dados existentes), use outra abordagem, como ter modelos de associação separados ou passar uma lista explícita de propriedades permitidas para UpdateModel ou TryUpdateModel. Adicionar um atributo [Bind(Include ="…")] em uma operação de Editar significa que o MVC criará uma instância do objeto e definirá apenas as propriedades listadas, deixando todos os outros valores padrão. Quando os dados forem persistidos, isso substituirá totalmente a entidade existente, redefinindo os valores de qualquer propriedade omitida para seus padrões. Por exemplo, se IsAdmin tiver sido omitido de um atributo [Bind(Include ="…")] em uma operação de Editar, qualquer usuário cujo nome tiver sido editado por meio dessa ação seria redefinido como IsAdmin = false (qualquer usuário editado perderia status de administrador). Se quiser impedir atualizações em determinadas propriedades, use um dos outros métodos acima. Observe que algumas versões das ferramentas do MVC geram classes de controlador com [Bind(Include ="…")] em ações de Editar e implicam que remover uma propriedade da lista impedirá os ataques de excesso de postagem. No entanto, conforme descrito acima, essa abordagem não funciona conforme o esperado e, em vez disso, redefinirá todos os dados nas propriedades omitidos para seus valores padrão.
  • Para operações de criação, há alguma restrição para usar [Bind(Include ="…")] em vez de modelos de associação separados? - Sim. Primeiro, essa abordagem não funciona para cenários de Edição, que exigem a manutenção de duas abordagens separadas para atenuar todas as vulnerabilidades de excesso de postagem. Em segundo lugar, modelos de associação separados impõem a separação de problemas entre a forma usada para a 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 ="…")] pode lidar apenas com propriedades de nível superior; você não pode permitir somente partes de subpropriedades (por exemplo, "Details.Name") no atributo. Por fim, e talvez mais importante, usar [Bind(Include ="…")] adiciona uma etapa extra que deve ser lembrada sempre que a classe é usada para model binding. Se um novo método de ação for associado à classe de dados diretamente e esquecer de incluir um atributo [Bind(Include ="…")], ele poderá ficar vulnerável a ataques de excesso de postagem, de forma que a abordagem com [Bind(Include ="…")] é um pouco menos segura por padrão. Caso você use [Bind(Include ="…")], tome cuidado para sempre se lembrar de especificá-lo toda vez que suas classes de dados forem exibidas como parâmetros de método de ação.
  • Para operações de Criar, é possível colocar o atributo [Bind(Include ="…")] na própria classe do modelo? Essa abordagem não evita a necessidade de se lembrar de colocar o atributo em cada método de ação? - Essa abordagem funciona em alguns casos. Usar [Bind(Include ="…")] no próprio tipo de modelo (e não nos parâmetros de ação que usam essa classe) evita a necessidade de se lembrar de incluir o atributo [Bind(Include ="…")] em cada método de ação. Usar o atributo diretamente na classe efetivamente cria uma área de superfície separada dessa classe para fins de model binding. No entanto, essa abordagem só permite uma forma de model binding por classe de modelo. Se um método de ação precisar permitir que o model binding de um campo (por exemplo, uma ação somente de administrador que atualiza funções de usuário) e outras ações precisarem impedir o model binding desse campo, essa abordagem não funcionará. Cada classe pode ter apenas uma forma de model binding. Se ações diferentes precisarem de formas de model binding diferentes, elas precisarão representar essas formas separadas usando classes de model binding separadas ou atributos [Bind(Include ="…")] separados nos métodos de ação.
  • O que são modelos de associação? Eles são a mesma coisa que os modelos de exibição? - São dois conceitos relacionados. O modelo de associação de termo se refere a um modelo de classe usado em uma ação e é a lista de parâmetros (a forma passada do model binding MVC para o método de ação). O modelo de exibição do termo se refere a uma classe de modelo passada de um método de ação para um modo de exibição. Usar um modelo específico de modo de exibição é uma abordagem comum para transmitir dados de um método de ação para um modo de exibição. Muitas vezes, essa forma também é adequada para model binding, e o modelo de exibição de termo pode ser usado para referenciar o mesmo modelo usado em ambos os locais. Em termos mais precisos, esse procedimento aborda especificamente a associação de modelos, concentrando-se na forma passada para a ação, o que importa para fins de atribuição em massa.

Codifique a saída da Web não confiável antes da renderização

Title Detalhes
Componente Aplicativo Web
Fase do SDL Build
Tecnologias aplicáveis Genérico, Formulários da Web, MVC5, MVC6
Atributos N/D
Referências Como evitar scripts entre sites no ASP.NET, Scripts entre sites, Folha de consulta de prevenção de XSS (Cross Site Scripting)
Etapas Scripts entre sites (frequentemente abreviados como XSS) são um vetor de ataque para serviços online ou qualquer aplicativo/componente que consuma a entrada da Web. As vulnerabilidades de XSS podem permitir que um invasor execute o script no computador de outro usuário por meio de um aplicativo Web vulnerável. Scripts mal-intencionados podem ser usados para roubar cookies e adulterar máquina da vítima por meio de JavaScript. O XSS é impedido pela validação da entrada do usuário, garantindo que ele seja bem-formado e codificado antes de ser renderizado em uma página da Web. A validação de entrada e a codificação de saída podem ser feitas usando a Web Protection Library. 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 

Execute a validação de entrada e a filtragem em todos os tipos de cadeia de caracteres de propriedades do modelo

Title Detalhes
Componente Aplicativo Web
Fase do SDL Build
Tecnologias aplicáveis Genérico, MVC5, MVC6
Atributos N/D
Referências Adicionando Validação, Validando Dados de Modelo em um Aplicativo MVC, Princípios Básicos para Aplicativos ASP.NET MVC
Etapas

Todos os parâmetros de entrada devem ser validados antes de serem usados no aplicativo, para garantir que o aplicativo esteja 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 de permissões. Entradas do usuário/parâmetros não corrigidos 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 executadas após o model binding:

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

A limpeza deve ser aplicada em campos de formulário que aceitam todos os caracteres, como o editor de rich text

Title Detalhes
Componente Aplicativo Web
Fase do SDL Build
Tecnologias aplicáveis Genérico
Atributos N/D
Referências Codificar a entrada não segura, HTML Sanitizer
Etapas

Identifica todas as marcas de marcação estática 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, codifique-os em HTML. Isso torna qualquer script mal-intencionado seguro, fazendo com que ele deva ser tratado como texto, não como código executável.

  1. Desabilite a validação de solicitação do ASP.NET adicionando o atributo ValidateRequest="false" à diretiva @ Page
  2. Codificar a entrada de cadeia de caracteres com o método HtmlEncode
  3. Use 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 desabilita a validação de solicitação ASP.NET definindo ValidateRequest="false". Ele codifica a entrada com HTML e permite seletivamente <b> e <i>. Como alternativa, uma biblioteca .NET para a limpeza de HTML também pode ser usada.

HtmlSanitizer é uma biblioteca .NET para limpeza de fragmentos HTML e documentos para impedir constructos que possam levar a ataques de XSS. Ele usa AngleSharp para analisar, manipular e renderizar HTML e CSS. HtmlSanitizer pode ser instalado como um pacote do NuGet, e a entrada do usuário pode ser passada por métodos de limpeza HTML ou CSS relevantes, conforme aplicável, no lado do servidor. Observe que a limpeza como um controle de segurança deve ser considerada apenas como último recurso.

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

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

Title Detalhes
Componente Aplicativo Web
Fase do SDL Build
Tecnologias aplicáveis Genérico
Atributos N/D
Referências N/D
Etapas Muitas funções de JavaScript não fazem a codificação por padrão. Ao atribuir entradas não confiáveis para elementos DOM por meio de funções, isso pode resultar em execuções de scripts entre sites (XSS).

Exemplo

A seguir estão exemplos não seguros:

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

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

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

Title Detalhes
Componente Aplicativo Web
Fase do SDL Build
Tecnologias aplicáveis Genérico
Atributos N/D
Referências Estrutura de autorização OAuth 2.0 - redirecionadores abertos
Etapas

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

Para fazer isso:

  • Identificar todos os redirecionamentos
  • Implemente uma atenuação apropriada para cada tipo de redirecionamento. Atenuações apropriadas incluem a confirmação de usuário ou a lista de permissões de redirecionamento. Se um site ou serviço com uma vulnerabilidade de redirecionamento aberto usar provedores de identidade Facebook/OAuth/OpenID, um invasor poderá roubar o token de logon do usuário e representar o usuário. Esse é um risco inerente ao usar OAuth, o que está documentado em RFC 6749 "A Estrutura de Autorização OAuth 2.0", Seção 10.15, "Redirecionamentos Abertos". Da mesma forma, as credenciais de usuário podem ser comprometidas por ataques de spear phishing usando redirecionamentos abertos

Implemente a validação de entrada em todos os parâmetros de tipo de cadeia de caracteres aceitos por métodos do Controlador

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

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

Title Detalhes
Componente Aplicativo Web
Fase do SDL Build
Tecnologias aplicáveis Genérico, Formulários da Web, MVC5, MVC6
Atributos N/D
Referências Propriedade DefaultRegexMatchTimeout
Etapas Para impedir ataques de negação de serviço contra expressões regulares criadas incorretamente, o que causa muito retrocesso, defina o tempo limite padrão global. Se o tempo de processamento for mais longo do que o limite superior definido, ela lançará uma exceção de tempo limite. Se nada estiver configurado, o tempo limite seria infinito.

Exemplo

Por exemplo, a configuração a seguir lançará RegexMatchTimeoutException se o processamento levar mais de cinco segundos:

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

Evite usar Html.Raw nos modos de exibição do Razor

Title Detalhes
Componente Aplicativo Web
Fase do SDL Build
Tecnologias aplicáveis MVC5, MVC6
Atributos N/D
Referências N/D
Etapa Páginas da Web do ASP.Net (Razor) executam a codificação HTML automática. Todas as cadeias de caracteres impressas por nuggets de código inserido (blocos @) são codificadas em HTML automaticamente. No entanto, quando o método HtmlHelper.Raw é invocado, ele retorna uma marcação que não é codificada em HTML. Se o método auxiliar Html.Raw() for usado, ele ignorará a proteção de codificação automática que o Razor fornece.

Exemplo

A seguir está um exemplo não seguro:

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

Não use Html.Raw(), a menos que você precise exibir a marcação. Esse método não executa implicitamente a codificação de saída. Use outros auxiliares do ASP.NET; por exemplo, @Html.DisplayFor()

Não use consultas dinâmicas em procedimentos armazenados

Title Detalhes
Componente Banco de dados
Fase do SDL Build
Tecnologias aplicáveis Genérico
Atributos N/D
Referências N/D
Etapas

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 o aplicativo usa a entrada para construir instruções SQL dinâmicas para acessar o banco de dados. Isso também poderá ocorrer se o código usar procedimentos armazenados que sejam cadeias de caracteres passadas que contenham 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. Instruções SQL parametrizadas aceitam caracteres que têm significado especial para o SQL (como aspas simples) sem problemas, pois eles são fortemente tipados.

Exemplo

A seguir está um exemplo de Procedimento Armazenado dinâmico não seguro:

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

Verifique se a validação do modelo é feita nos métodos de API Web

Title Detalhes
Componente API Web
Fase do SDL Build
Tecnologias aplicáveis MVC5, MVC6
Atributos N/D
Referências Validação de modelo na ASP.NET Web API
Etapas Quando um cliente envia dados a uma API Web, é obrigatório validar os dados antes de executar qualquer processamento. Para ASP.NET Web APIs 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);
            }
        }
    }
}

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

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

Verifique se os parâmetros de tipo seguro são usados na API Web para acesso a dados

Title Detalhes
Componente API Web
Fase do SDL Build
Tecnologias aplicáveis Genérico
Atributos N/D
Referências N/D
Etapas

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

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

Exemplo

O código a seguir mostra como usar parâmetros de tipo seguro com 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 ter mais de 11 caracteres. Se os dados não estão de acordo com o tipo ou o comprimento definido pelo parâmetro, a classe SqlParameter lança uma exceção.

Usar consultas SQL parametrizadas no Azure Cosmos DB

Title Detalhes
Componente Azure Document DB
Fase do SDL Build
Tecnologias aplicáveis Genérico
Atributos N/D
Referências Anunciando a parametrização de SQL no Azure Cosmos DB
Etapas Embora o Azure Cosmos DB dê suporte apenas a consultas somente leitura, a injeção de SQL ainda será possível se as consultas forem construídas concatenando com a entrada do usuário. É possível que um usuário obtenha acesso a dados que não deveria acessar na 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 de WCF por meio de associação de esquema

Title Detalhes
Componente WCF
Fase do SDL Build
Tecnologias aplicáveis Genérico, NET Framework 3
Atributos N/D
Referências MSDN
Etapas

A ausência de validação leva a ataques de injeção de tipo diferente.

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

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

Validação de entrada de WCF por meio de Inspetores de Parâmetro

Title Detalhes
Componente WCF
Fase do SDL Build
Tecnologias aplicáveis Genérico, NET Framework 3
Atributos N/D
Referências MSDN
Etapas

A validação de dados e entrada representa uma linha de defesa importante na proteção do aplicativo WCF. Você deve validar todos os parâmetros expostos em 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&e-lo contra ataques de um serviço mal-intencionado

O WCF fornece pontos de extensibilidade diferentes que permitem que você personalize o comportamento de runtime do WCF criando extensões personalizadas. Inspetores de mensagem e inspetores de parâmetro 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âmetro para validação de entrada e usar inspetores de mensagem somente quando precisar inspecionar a mensagem inteira 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âmetro personalizado para validar parâmetros nas operações no 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 de ponto de extremidade personalizado estendido no arquivo de configuração do serviço ou cliente