Entradas e saídas

Concluído

Atualmente, a vulnerabilidade de segurança mais predominante dos aplicativos é não processar corretamente os dados recebidos de fontes externas, particularmente a entrada do usuário. Sempre analise de perto qualquer entrada para garantir que ela foi validada antes de ser usada. Não analisar a entrada do usuário para possíveis ataques pode resultar na perda de dados ou exposição, elevação de privilégio ou até mesmo a execução de código mal-intencionado nos computadores de outros usuários.

A tragédia nessa situação é que esse cenário é um problema fácil de resolver. Nesta unidade, abordaremos como tratar os dados; no recebimento, exibição na tela e armazenamento para uso posterior.

Por que precisamos validar nossa entrada?

Imagine que você esteja criando uma interface para permitir que um usuário crie uma conta em seu site. Nossos dados de perfil incluem um nome, email e um apelido que será exibido para todas as pessoas que visitam o site. E se um novo usuário criar um perfil e inserir um apelido que inclui alguns comandos SQL? Por exemplo – e se um usuário mal-intencionado inserir algo semelhante ao seguinte trecho:

Eve'); DROP TABLE Users;--

Se inserirmos esse valor em um banco de dados, ele poderá alterar a instrução SQL para executar comandos absolutamente indesejados! Isso é conhecido como um ataque de "injeção de SQL" e é um dos muitos tipos de explorações que podem ser feitas quando você não trata corretamente as entradas do usuário. O que podemos fazer para corrigir essa situação? Esta unidade ensinará a você quando validar a entrada, como codificar a saída e como criar consultas parametrizadas (que resolvem a exploração acima). Essas são as três técnicas de defesa principais contra entrada mal-intencionada em seus aplicativos.

Quando é necessário validar a entrada?

A resposta é sempre. Você deve validar toda entrada em seu aplicativo. Isso inclui parâmetros na URL, entrada do usuário, dados do banco de dados, dados de uma API e qualquer coisa passada sem criptografia que um usuário possa manipular. Sempre use uma abordagem de lista de permitidos, o que significa que você aceita apenas entradas "conhecidamente válidas", em vez de uma lista de bloqueados (em que você procura especificamente uma entrada incorreta), porque é impossível pensar em uma lista completa de entradas possivelmente perigosas. Faça esse trabalho no lado do servidor, e não no lado do cliente (ou além do lado do cliente), para garantir que suas defesas não possam ser contornadas. Trate TODOS os dados como não confiáveis, e você se protegerá da maioria das vulnerabilidades comuns de aplicativos Web.

Se você estiver usando ASP.NET, a estrutura oferecerá um excelente suporte para a validação de entrada no lado do cliente e do servidor.

Se estiver usando outra estrutura da Web, há algumas técnicas excelentes para fazer a validação da entrada disponíveis na Folha de referência de validação de entrada do OWASP.

Sempre use consultas parametrizadas

Os bancos de dados SQL são normalmente usados para armazenar dados. Por exemplo, o aplicativo pode armazenar informações do perfil do usuário em um banco de dados. Nunca crie consultas SQL embutidas ou outras consultas de banco de dados no seu código usando a entrada bruta do usuário e as envie diretamente para o banco de dados. Esse comportamento resulta em desastre, como vimos anteriormente.

Por exemplo, não crie um código como o seguinte exemplo de SQL embutido:

string userName = Request.QueryString["username"]; // receive input from the user BEWARE!
...
string query = "SELECT *  FROM  [dbo].[users] WHERE userName = '" + userName + "'";

Aqui, concatenamos cadeias de caracteres de texto para criar a consulta, recebendo a entrada do usuário e gerando uma consulta SQL dinâmica para pesquisar o usuário. Novamente, se um usuário mal-intencionado perceber que estamos fazendo isso ou apenas tentar estilos diferentes de entrada para ver se há uma vulnerabilidade, poderemos sofrer um grande desastre. Em vez disso, use instruções SQL parametrizadas ou procedimentos armazenados como este:

-- Lookup a user
CREATE PROCEDURE sp_findUser
(
@UserName varchar(50)
)

SELECT *  FROM  [dbo].[users] WHERE userName = @UserName

Com esse método, você pode invocar o procedimento de seu código com segurança, passando a ele a cadeia de caracteres userName, sem se preocupar que isso será tratado como parte da instrução SQL.

Sempre codifique sua saída

Qualquer saída que você apresente visualmente ou dentro de um documento sempre deverá ser codificada e ignorada com escape. Isso pode proteger você caso deixe passar algo na fase de limpeza ou caso o código gere algo que possa ser usado de maneira mal-intencionada. Esse princípio de design garantirá que tudo seja exibido como saída e não seja acidentalmente interpretado como algo que deva ser executado, o que é outra técnica de ataque comum conhecida como XSS (Cross-Site Scripting).

Como a prevenção contra XSS é um requisito comum do aplicativo, essa técnica de segurança é outra área em que o ASP.NET fará o trabalho para você. Por padrão, toda a saída já está codificada. Se você estiver usando outra estrutura da Web, verifique as opções de codificação de saída nos sites do OWASP XSS Prevention Cheatsheet (Folha de referência de prevenção de XSS do OWASP).

Resumo

A limpeza e a validação da entrada são requisitos necessários para garantir que ela seja válida e segura para usar e armazenar. A maioria das estruturas da Web modernas oferece recursos internos que podem automatizar parte desse trabalho. É possível verificar a documentação da sua estrutura favorita e ver que recursos ela oferece. Embora os aplicativos Web sejam o lugar mais comum em que isso acontece, lembre-se de que outros tipos de aplicativos podem estar tão vulneráveis quanto. Não acho que você esteja seguro só porque seu novo aplicativo é um aplicativo da área de trabalho. Você ainda precisará lidar adequadamente com a entrada do usuário para garantir que ninguém use seu aplicativo para corromper seus dados ou manchar a reputação da sua empresa.

Verificar seu conhecimento

1.

Qual das seguintes fontes de dados precisam ser validadas?

2.

As consultas parametrizadas (procedimentos armazenados no SQL) são uma maneira segura de comunicar-se com o banco de dados, porque:

3.

Qual tipo de dados a seguir precisa ser codificado na saída?