Quadro de segurança: Validação de entrada | Atenuações
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 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:
|
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:
|
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 |
|
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:
|
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 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.
A página nas referências desabilita a validação de solicitação ASP.NET definindo 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:
|
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 |