SQL Injection, como o nome já diz, se trata de injeções de comandos ao banco de dados através de parâmetros que podem ser alterados pelos usuários da aplicação, inserindo instruções a mais nas consultas ao banco de dados, devemos cuidar muito bem praticamente todos os campos de parâmetros, tanto parâmetros que utilizam GET ou POST, pois existe a possibilidade de estarmos trabalhando com pessoas capacitadas e que tenham conhecimento técnico, e um POST é fácil de ser interceptado e manipulado assim como o GET pode ser visível na URL no browser do usuário.
Através de um GET, por exemplo, injetando um apóstrofo ( ‘ ) ou aspas simples como preferirem, a aplicação pode retornar erros vindos do Banco de Dados, como exemplo temos a seguir algumas imagens de erros que possibilitam injeções de SQL, erros originados através de testes efetuados por nossa equipe.
Erros em ORACLE
Figura 1 – invalid number inserindo um apóstrofo
Figura 2 – quoted string not properly terminated
Nesta aplicação reparem que conforme o erro, o banco de dados retorna o tipo de problema que ele obteve ao fazer a consulta de certificado, Figura 1 ele nos alerta que o número inserido é inválido, na figura 2 o erro já muda, nos mostrando que nossa String de referência não foi devidamente encerrada, neste caso a injeção se deu através de parâmetros GET, ou seja, na própria URL do sistema, onde é possível a inserção de comandos SQL.
Erros em MySQL
Exemplo de inserção do apóstrofo: productos.php?id=5′
Erro retornado:
Figura 3 – Erro retornado por MySQL
Como podemos perceber o erro retornado já nos fornece diretamente sem nenhum filtro como o SELECT é formado, facilitando ainda mais a inserção de comandos SQL na URL do sistema Web afetado.
Erros em MSSQL
Exemplo de inserção do apóstrofo: detalles.php?id=1’
Erro retornado:
Figura 4 – Erro retornado pelo MSSQL
Conforme podemos visualizar na imagem, o erro retornado muitas vezes vem com informações sensíveis ao sistema web, não só informações do banco de dados, facilitando o trabalho de um atacante, como podem perceber, nos foi retornado inclusive o diretório onde a aplicação e demais aplicações se encontram no servidor.
Evitando SQL Injection
Como vimos anteriormente, a simples inserção de caracteres especiais nos parâmetros de aplicações web, ocasionam erros retornados muitas vezes pelo próprio Banco de Dados, para evitarmos este tipo de problema, vamos citar exemplos em algumas linguagens.
Limpeza de variáveis
Ao receber os parâmetros, não importa o jeito que o mesmo foi direcionado para a aplicação, em muitas linguagens existe a possibilidade de fazer um replace, como exemplo, temos a seguir replaces feitos em asp para a filtragem de possíveis entradas maliciosas nos parâmetros:
Código 1 – Exemplo de função em asp para retirada de caracteres especiais
Existem diversas formas de limpar variáveis, outra forma é criar um Array com caracteres especiais, e fazer dentro de um laço for, verificar se o caractere existe no conteúdo da variável recebida, se existir, limpar usando um replace. Existem diversas linguagens que utilizam o recurso de Replace, exemplo acima, temos a ASP, porém existe também em linguagens exemplo, Java, PHP, dentre outras linguagens utilizadas em programação web.
Evitar concatenação de variáveis em Querys
Atualmente com a vinda de novas linguagens web, temos como evitar a concatenação de conteúdos vindos através de parâmetros, dentro de Strings que formariam as Query’s para consultas ao banco de dados, erro bem comum em programação web, pois se trata da primeira possibilidade de fazer uma consulta “bem sucedida” ao banco de dados para uma pessoa iniciante em programação web, exemplos que não devemos seguir:
Código 2 – Exemplo ao qual devemos evitar fazer
Atualmente temos como evitar esse tipo de inserção ao banco de dados, assim evitando a possibilidade de ocorrer SQL Injection, conforme irei especificar a seguir em .NET utilizando Parameters,
Código 3 – Exemplo de Parameters em .NET
Assim como existe essa forma de evitar SQL Injection no framework do .NET existem outras formas de evitar concatenações em Querys, o Java também possui os PreparedStatements, exemplo,
Código 4 – Exemplo de PreparedStatements em Java
Para inserirmos Strings em um PreparedStatement utilizamos a seguinte opção:
Código 5 – Exemplo de setString em um PreparedStatement
Lembramos que esse exemplo é baseado no exemplo do Código 4 porém como não existe o 3º campo a ser preenchido na variável PreparedStatement, isso foi somente um exemplo, se repararmos os caracteres “?” (Interrogação) simbolizam a ordem dos Set’s no PreparedStatement, ainda no Código 4 podemos observar por exemplo,
Código 6 – Demonstração setInt
Ao qual insere o valor 110592 no campo “ID = ?” do PreparedStatement , ficando a Query assim ID = 110592.
Se por um acaso, a variável SALARY for manipulada, por exemplo, inserir o valor 153833.00’, no banco de dados irá ser atualizado a célula de salário para 153833.00’ não afetando em injeções de comandos SQL. Mas sim somente causando uma “poluição” do banco de dados com caracteres especiais desnecessários.
Tratamento em telas de erro
Atualmente, algumas linguagens, exemplo, Java e C#, ou .NET, contém formas de contornar e tratar erros, os famosos “try catch” , a seguir exemplifico em Java, porém em .NET é muito similar,
Código 7 – Exemplo de tratamento seguro em erros
Conforme foi demonstrado no Código 7, no segundo comentário, dentro da instrução catch, devemos esconder absolutamente todas as variáveis que podem mostrar dados, ao qual muitas vezes ajudam um atacante a obter informações sobre o sistema, como temos a variável ex podemos usa-la para selecionar o tipo de tela de erro, cuidando também para não facilitarmos que um atacante descubra, por exemplo, a existência de um usuário no sistema, telas de erro em HTML que ajudem a equipe de suporte a diagnosticar o problema, sem impressão de variáveis, simplesmente pela mensagem, escolhida entre if’s que comparem a variável “ex” com certos tipos de Exceptions esperados, que podem ser retornados pela aplicação.
Evitando ataques “cegos”
Ataques cegos de injeção SQL, ou Blind SQL Injection, se trata do atacante tentar adivinhar o que existe no banco de dados, por exemplo, com uma sentença, a página pode retornar 1 para true, ou 0 para false, assim o atacante pode obter êxito na sua exploração, consultando a existência dos dados, outra forma de evitar esse tipo de ataque é através do replace na aplicação web, da função SQL “sleep()” que muitos SGBD’s hoje em dia carregam, ao qual faz o Banco de Dados ter um delay ao responder para a aplicação web, quando o valor consultado existir no banco de dados.
Outras formas eficientes de evitar este e outros ataques à aplicações web?
Existe sim outras formas de evitar este e outros tipos de ataques em aplicações web, nossa empresa desenvolveu o XLabs Web Application Firewall, trata-se de um sistema que defende qualquer plataforma web de ataques direcionados a tais aplicações. Quer saber mais? Fale agora mesmo com um de nossos especialistas.