SQL Injection
é uma técnica usada por hackers
(crackers) para executar
comandos SQL não autorizados e
assim obter vantagem de
aplicações que utilizam queries
SQL dinâmicas.
Exemplo:
Considere a seguinte query:
Código PHP:
<?php
mysql_connect('localhost', 'user',
'pass') OR die(mysql_error());$query
= ”SELECT * FROM users WHERE
user=’”.$_POST['username'].”‘
AND password=’”.$_POST['password'].”‘”;
mysql_query($query);
?>
Ela pode ser usada para
autenticar um usuário, como em
um login.
Nós não verificamos os dados
enviados pelo usuário,
$_POST['username']
e
$_POST['password'], sendo assim
ele pode enviar qualquer coisa,
por exemplo:
Código PHP:
$_POST['username'] = 'admin';
$_POST['password'] = "' OR
''='";
A query ficará assim:
Código:
SELECT * FROM users WHERE user='admin'
AND password=' ' OR ' '=' '
Ela permite que qualquer um faça
o login sem uma senha válida.
Exemplo 2:
O SQL Injection pode ser bem
mais perigoso como o seguinte
exemplo.
Código PHP:
<?php
mysql_connect('localhost', 'user',
'pass') OR die(mysql_error());
$query = "SELECT * FROM users
WHERE name = '".$_POST['name']."'";
mysql_query($query);
?>
Um usuário poderá enviar para
nossa query o seguinte código:
Código PHP:
$_POST['name'] = "a';DROP TABLE
users";
e ela ficará assim:
Código:
SELECT * FROM users WHERE name =
'a'; DROP TABLE users
Ela selecionará o usuário com
nome igual a ‘a’ e logo após irá
apagar nossa tabela ‘users’.
Como Evitar o SQL injection
Para evitar é necessário que
sempre sejam validados os dados
enviados pelo usuário. O PHP nos
fornece uma função para tratar
este problema. É a
mysql_real_escape_string()
Exemplo:
Podemos solucionar o SQL
Injection do primeiro exemplo da
seguinte maneira:
Código PHP:
<?php
mysql_connect('localhost', 'user',
'pass') OR die(mysql_error());$user
=
mysql_real_escape_string($_POST['username']);
$pass =
mysql_real_escape_string($_POST['password']);$query
= ”SELECT * FROM users WHERE
user=’$user’ AND
password=’$pass’ ”;
mysql_query($query);
?>
A query ficará assim:
Código:
SELECT * FROM users WHERE user='admin'
AND password=' ' OR ' '=' ''
e elá não permitirá mais que
qualquer um faça o login sem
possuir uma senha válida.
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():
Código PHP:
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(). 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:
Código PHP:
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 protegidos
contra ataques de SQL Injection,
e o melhor de tudo, sem destruir
o conteúdo dos nossos sistemas.
Sem comentários:
Enviar um comentário