Fala galera, tudo tranquilo?!

Neste post daremos continuidade a nossa seŕie de posts para prevenção de SQL injection, caso você ainda não tenha lido nosso primeiro post “Defesa eficaz contra SQL Injection – Introdução” recomendo a leitura para que assim você possa usufruir com maior qualidade dos textos.

Todo sistema, sendo ele desktop, mobile ou web ele recebe dados transmitidos pelo usuário, podendo ser um simples formulário para coleta de e-mail até informações complexas como controle de fluxo orçamentário da empresa. E o ponto comum neste processo é o tráfego de informações entre o sistema e o banco de dados. Para mantermos este elo seguro devemos empregar SEMPRE uma boa prática sendo ela: validar e filtrar “input” e “output”. E o que seria isso? Pois bem vamos detalhar um pouco mais esse processo com nosso caso de uso.

Para nosso caso de uso usaremos uma ação de login, onde o usuário deve informar seu e-mail e senha para ter acesso ao sistema e seus dados, esse caso de uso é excelente pois estamos habituados com o ciclo de uma autenticação no sistema, ficando assim mais fácil focar nos conceitos do post.

Sempre que formos manipular os dados para enviar ao servidor e consecutivamente ao banco de dados, temos que garantir que os dados que estamos recebendo de fato correspondem com o desejado, evitando assim quaisquer informação indesejada vindo do cliente, sempre temos que partir do pressuposto que nada vindo do usuário é seguro e que sempre devemos nos prevenir da melhor maneira possível, fazendo isso teremos uma aplicação muito mais segura.

Primeiro ponto que gostaria de salientar, caso você vá transmitir dados para o servidor, sempre dê preferência em trafegar os dados pelo meio do método “POST” em detrimento do “GET”, fazendo isso os dados não ficam “visíveis” para o usuário na “URL”.

Após o envio dos dados vamos iniciar nosso processo de filtragem de dados e como exemplo utilizarei o PHP para demonstrar algumas maneiras eficazes de fazer esse processo, porem todo conceito apresentado aqui vale para qualquer outra linguagem de programação.

É muito comum encontrarmos códigos PHP deste tipo:

1
2
3
4
5
6
<?php

$email = $_POST['email'];
$senha = $_POST['senha']

$querySQL = 'SELECT * FROM users WHERE email = '.$email.' AND senha = '. $senha. ' ;';

E aqui entra os pontos do porque isso é inseguro, pois é passado de forma direta os dados recebidos do formulário e inserido na consulta SQL. Está prática não garante em nada a integridade dos dados recebidos deixando nosso sistema vulnerável para receber instruções para manipulação do nosso banco de dados.

Então, como uma regra que gostaria de fazer com vocês é NUNCA DEVEMOS passar qualquer tipo de informação para nossa consulta SQL sem antes validar sua estrutura!

filter_input

Para substituirmos nosso famigerado $_POST, podemos utilizar uma função nativa do PHP para fazer a coleta e validação da informação já no ato em que recebemos os dados, vejamos o exemplo abaixo:

1
2
3
4
<?php

$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$senha = filter_input(INPUT_POST, 'senha');

Como podemos analisar, ao chamarmos a função “filter_input” no primeiro parâmetro informado determinamos o tipo de origem da informação, no segundo parâmetro informamos o nome do campo que desejamos receber e por último informamos que desejamos validar se o dado recebido é um e-mail.

Essa função suporta receber o seguintes valores da request HTTP:

  • INPUT_GET
  • INPUT_POST
  • INPUT_COOKIE
  • INPUT_SERVER
  • INPUT_ENV

E caso desejamos validar com mais filtros nosso input basta inserir uma virgula e informar o próximo parâmetro. Caso não seja informado nenhum validador, como no caso do campo de senha, por default a função utiliza “FILTER_DEFAULT”.

Caso a informação recebida pelo “filter_input” não corresponda com o especificado seu retorno será “false”, caso a variável não seja definida retornará “null”.

filter_var

Temos como alternativa a função filter_var, vejamos no exemplo abaixo:

1
2
3
4
<?php

$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
$senha = filter_var($_POST['senha']);

Executa uma ação similar ao “filter_input” porém suas diferenças são:

  • Devemos inserir a informação que desejamos filtrar.
  • Caso não seja informado um filtro específico o mesmo utiliza por “default” o “FILTER_SANITIZE_STRING”.
  • Caso valor informado não corresponda com o filtro desejado seu retorno será “false”.

As duas funções apresentadas acima já insere uma camada de verificação nos dados recebidos, porém no universo PHP dispomos de bibliotecas que fazem a função de validar e filtrar os dados de forma excepcional, abaixo podemos ver algumas dessas ferramentas.

  • Zend
    • Zend-Filter
    • Zend-Validator
    • Duas ferramentas fantásticas disponíveis no Zend Framework que podem ser utilizadas de forma isolada porém, em conjunto são poderosíssimas.
  • Symfony
    • Validation
    • Ferramenta de iqual poder disponibilizada pela equipe do framework Symfony,  fornecendo uma gama de opções para configurar suas validações ,como por exemplo: “Annotations”, “Yaml”, “PHP” e “XML”.
  • Respect
    • Validation
      • Ferramenta “Brazuca”, demonstrando a qualidade do código produzido no Brasil, muito simples de se utilizar pois usa arquitetura modular, permite que você possa trabalhar em qualquer projeto utilizando essa biblioteca.

Eu particularmente recomendo que se faça uso de alguma ferramenta de mercado, podendo ser uma das listadas acima ou outra de sua preferência, pois essas ferramentas tem uma equipe de programadores contribuindo para seu crescimento e aperfeiçoamento, nas correções de bugs e por mais que você se empenhe em construir sua própria biblioteca, esse processo será longo e custoso e na grande maioria dos projetos que participamos em nosso dia a dia eles não dispõem de tempo para tal abordagem.

Claro que se você gostaria de construir um conjunto de ferramenta para praticar e estudar é totalmente válido e recomendo.

Espero que neste post eu tenha transmitido a importância que se é o tratamento de dados, pois é uma prática inegociável independente de prazo ou tecnologia, sempre devemos ter como padrão esta boa prática.

No próximo post “Defesa eficaz contra SQL Injection – Comunicação com o banco de dados” irei abordar uma forma eficaz de comunicação com o banco de dados e como podemos realizar as ações no banco sem dores de cabeça.

Até o próximo post 🙂