Olá a todos, desculpem pela ausência, por algum motivo (algo relacionado com o Speedy) eu não estava conseguindo acessar o meu blog o que me impossibilitava de escrever, i’m sorry.
Hoje vou falar um pouco sobre como funciona o SQL Injection e como podemos proceder para que nós não sejamos pegos por este tipo de vulnerabilidade.
O que é SQL Injection?
SQL Injection é uma técnica de injeção de código que explora uma vulnerabilidade de segurança localizada na camada de banco de dados (database layer) do servidor. Na prática é utilizada por hackers (ou não) para ter acesso ao banco de dados do servidor da vítima sem que ele precise de um login ou uma senha efetivamente para fazê-lo.
Como funciona o SQL Injection?
Para entendermos melhor como funciona os ataques via injeção de códigos SQL (SQL Injection), vou utilizar um caso bem comum entre os programadores para que vocês se familharizem com mais facilidade.
Pense em um formulário para login no sistema e uma consulta na base de dados para verificar se determinado usuário e senha existe em na base de dados.
Exemplo
SELECT usuario,senha FROM usuarios WHERE usuario = 'igorescobar' AND senha='123456'
O ataque acontece justamente no ponto, aonde o usuário preenche o usuário e a senha no formulário de login do site. Se você não filtra todos os dados que vem de FORA para DENTRO da sua aplicação, você corre o risco de ser atacado.
Na prática o código fica algo parecido com isso:
SELECT usuario,senha FROM usuarios WHERE usuario = '$usuario' AND senha='$senha';
Estas variáveis ($usuario e $senha) estão vindo do $_POST do seu formulário e o servidor iria interpretar assim:
SELECT usuario,senha FROM usuarios WHERE usuario = 'igorescobar' AND senha='123456';
Agora imagine que eu sou um usuário mal intencionado e desejo logar no servidor de vocês sem ser autorizado.
No campo senha vou inserir o seguinte conteúdo:
123456' OR 'a'='a
Vamos ver como fica?
SELECT usuario,senha FROM usuarios WHERE usuario = 'igorescobar' AND senha='123456' OR 'a'='a';
Hun… como diria eu mesmo (há!): F-U-D-E-U!
Quer outro exemplo? … um mais bacana?
Agora no campo senha eu vou inserir o seguinte conteúdo:
123456'; DROP TABLE usuarios; --
Vamos ver como fica?
SELECT usuario,senha FROM usuarios WHERE usuario = 'igorescobar' AND senha='123456'; DROP TABLE usuarios; --';
Ok, agora você já esta pronto para passar no RH 
Oh my god :O como eu me protejo dos ataques SQL Injection ?
Primeiro: Separe sempre a exibição de erros em 2 ambientes, o ambiente de desenvolvimento e o ambiente de produção. O ambiênte de desenvolvimento pode ter qualquer tipode erro emitido na tela, afinal, você precisa ver os erros para tratá-los, no ambiênte de produção omita qualquer tipo de erro, qualquer erro pode ser uma pista para o hacker descobrir detalhes sobre o seu ambiênte.
Ambiente de Desenvolvimento
<?php error_reporting(E_ALL ^ E_NOTICE); ?>
Ambiente de Produção
<?php error_reporting(0); ?>
Segundo: Filtre todo o tipo de variável dados que veem de urls ou inputs de formulário $_GET ou $_POST para que nenhum dos dados inputados pelo usuário possa ser interpretado como parte da instrução SQL.
Vale lembrar que o certo seria utilizarmos PDO que já tem uma proteção definitiva contra isso, pois ele tem o acesso ao modelo do seu banco de dados e pode fazer muito melhor do que uma simples filtrarem generica nos campos, ele pode filtrar cada campo dependendo do tipo de cada campo o que é muito melhor.
Caso você não use PDO, você pode utilizar também uma função chamada mysql_real_escape_string que também cumpre o que promete.
Solução definitiva para o SQL Injection
Está solução é válida apenas para as pessoas que não utiliza nenhuma das 2 (duas) soluções citadas acima.
<?php
/**
* Protege o banco de dados contra ataques de SQL Injection
*
* Remove palavras que podem ser ofensivas à integridade do banco
* Adiciona barras invertidas a uma string
*
* @uses $_REQUEST= _antiSqlInjection($_REQUEST);
* @uses $_POST = _antiSqlInjection($_POST);
* @uses $_GET = _antiSqlInjection($_GET);
*
* @author Igor Escobar
* @email blog [at] igorescobar [dot] com
*
*/
function _antiSqlInjection($Target){
$sanitizeRules = array('OR','FROM','SELECT','INSERT','DELETE','WHERE','DROP TABLE','SHOW TABLES','*','--','=');
foreach($Target as $key => $value):
if(is_array($value)): $arraSanitized[$key] = _antiSqlInjection($value);
else:
$arraSanitized[$key] = (!get_magic_quotes_gpc()) ? addslashes(str_ireplace($sanitizeRules,"",$value)) : str_ireplace($sanitizeRules,"",$value);
endif;
endforeach;
return $arraSanitized;
}
?>
Terceiro: Não tem, só estes 2 passos está bom 
ps: Desculpem as piadas, estou de bom humor hoje 
UPDATE(1): Acrescentei algumas palavras na blacklist da função
UPDATE(2): Troquei o str_replace para o str_ireplace e acrescentei a verificação de magic_quotes.
UPDATE(3): Retirei a função trim por não fazer diferença alguma rs.
[]’s
Igor.
Posts Relacionados: