Olá galera!
Hoje estou dando início aos meus artigos sobre programação aqui neste meu novo blog de tecnologia. A minha idéia é futuramente estar criando também algumas vídeo-aulas, para ajudar aqueles programadores iniciantes e que precisam de ajuda em algumas coisas que só programadores mais experientes sabem auxiliar.
Começarei falando sobre um assunto muito importante, que envolve a segurança dos nossos projetos em PHP e MySQL, o temido SQL Injection. Estarei adaptanto um artigo que criei há algum tempo atrás e publiquei em um blog antigo meu e também no site PHP Brasil.
Bom, se você é programador, certamente já ouviu falar sobre SQL Injection. O que poucos programadores sabem é como fazer uma função que evite de forma eficaz e não destrutiva este problema.
Resolvi fazer este artigo porque todos os dias que entro em algum fórum sobre o assunto, encontro várias pessoas perguntando qual é a melhor opção para evitar este problema, ou então dizendo que seu site acaba de ser atacado por um hacker e todo o seu banco de dados foi apagado ou alterado. E vendo as respostas de alguns programadores mais “avançados” dá vontade de rir de tantas coisas inúteis e destrutivas que eles fazem pra tentar evitar ataques de SQL Injection, e por incrível que pareça são as mais comuns e usadas por programadores de várias linguagens, como por exemplo remover palavras que são utilizadas em SQL, remover caracteres especiais e adicionar barras invertidas.
A maioria dos programadores usa e sugere o uso da função str_replace() para remover palavras como SELECT, DELETE, UPDATE, TRUNCATE, entre outras. Isso é simplesmente ridículo, pois se um usuário de um site por exemplo for falar de programação ou usar um desses termos em inglês eles simplesmente vão sumir, ou seja, vai destruir um texto sem ter necessidade.
Já outros programadores sugerem o uso da função addslashes(), que adiciona barras invertidas antes de aspas simples e duplas. Esta função é funcional, porém meio ultapassada e também estraga os textos, pois os internautas que visitarem um site irão achar feio e não irão entender o porque daquelas barras invertidas antes de cada aspas. É claro que é possível remover as barras nos dados vindos do banco com o auxílio da funcão stripslashes(), mas aí o trabalho é dobrado, pois estaremos tratando os dados na entrada e saída do banco também sem necessidade.
Ainda há programadores que usam funções como htmlspecialchars() e htmlentities(), que aumentam o volume dos dados no banco de dados e deixam elas como HTML sendo que em outras aplicações pode ser totalmente desnecessário e não compatível o uso desses caracteres.
Pois bem, vamos então falar do que realmente previne sistemas contra ataques de SQL Injection e sem “destruir” textos ou aumentar o volume no banco de dados.
A melhor função para proteger seus sistemas em PHP e MySQL contra SQL Injection é a mysql_real_escape_string(), ela escapa os caracteres especiais como aspas simples e duplas antes de enviar para o banco de dados. Porém esta função não funciona em todas as versões do PHP, então na função que iremos criar temos quer verificar se ela existe, e caso não exista vamos utilizar a função mysql_escape_string().
Também devemos ter em mente que se a diretiva get_magic_quotes_gpc() estiver ON ele irá acrescentar barras invertidas automaticamente antes de aspas simples e duplas, o problema é que ele irá enviar para o banco de dados com as barras invertidas, estragando o texto. Para contornar isso basta usar a função stripslashes() para remover essas barras invertidas.
Então vamos montar a nossa função com o nome de anti_sql_injection():
function anti_sql_injection($str) {
if (!is_numeric($str)) {
$str = get_magic_quotes_gpc() ? stripslashes($str) : $str;
$str = function_exists('mysql_real_escape_string') ? mysql_real_escape_string($str) : mysql_escape_string($str);
}
return $str;
}
Note que em nossa função primeiro verificamos se a o valor informado não é numérico, ou seja, que precisa ser tratado, em seguida verificamos se a diretiva get_magic_quotes_gpc() está ativada, se estiver usamos a função stripslashes() conforme falado anteriormente. Em seguida verificamos se existe a função mysql_real_escape_string(), se existir usamos ela, caso contrário usamos a função mysql_escape_string().
Veja um exemplo de como usar a função:
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$usuario = trim($_POST['usuario']);
$senha = trim($_POST['senha']);
$sql = 'SELECT COUNT(id_usuario) ';
$sql .= 'FROM usuarios ';
$sql .= 'WHERE usuario = \'' . anti_sql_injection($usuario) . '\' ';
$sql .= 'AND senha = \'' . anti_sql_injection($senha) . '\' ';
$query = mysql_query($sql) or die('Erro na consulta: ' . mysql_error());
$total = mysql_result($query, 0);
if ($total > 0) {
echo 'Usuário e senha corretos.';
} else {
echo 'Usuário e/ou senha inválidos.';
}
}
Pronto! Estamos vacinados contra ataques de SQL Injection, e o melhor de tudo, sem destruir o conteúdo dos nossos sistemas.
Abraços e até a póxima!