Canais iMasters

PHP

SQL Injection no PHP: O que é e como se proteger

A segurança das informações é um assunto que exige atenção especial, principalmente em se tratando de informações armazenadas em bancos de dados acessados via web.

Uma das técnicas de fraude mais conhecida pelos desenvolvedores web é a SQL Injection. Trata-se da manipulação de uma instrução SQL através das variáveis quem compõem os parâmetros recebidos por um script server-side, tal como PHP, ASP, ColdFusion e outros.

O principal motivo pelo qual deve-se impossibilitar a utilização da SQL Injection está no fato de que, através de uma simples instrução SQL, como por exemplo, uma projeção de dados, outras operações podem ser executadas, podendo impactar sobre o esquema das tabelas, os dados armazenados, e até mesmo sobre elementos do sistema operacional, tendo em vista que alguns bancos de dados permitem a execução de comandos do shell do próprio sistema operacional.

Detectando a vulnerabilidade de um sistema

Para ilustrar o conceito de SQL Injection, a seguinte simulação pode ser realizada. Imaginemos que um script de validação de acesso de usuários tenha sido desenvolvido como segue:

Nas linhas 3 e 4, as variáveis $usuario e $senha, respectivamente, recebem o conteúdo submetido por um formulário através do método POST. Eis a fonte do problema.

Suponha que a seguinte entrada tenha sido informada no campo usuário no formulário chamador do script de validação.

Logo, a query string resultante será:

Se nenhuma outra validação for realizada, o usuário mal intencionado terá efetuado login no sistema, sem ao menos informar um usuário contido na tabela. Isto foi possível pois o valor de entrada informado não recebeu o tratamento devido, sendo adicionado à instrução para ser executado. Vale ressaltar que as validações apresentadas no exemplo são apenas ilustrativas, havendo a necessidade de checagens mais eficazes para um script de validação de acesso.

Impossibilitando o uso de SQL Injection

Para que se esteja livre da utilização da SQL Injection, certas providências devem ser tomadas. Algumas das ações serão realizadas no servidor de banco de dados, outras devem ser garantidas pelo código fonte.

Deve-se tomar cuidado com a configuração do usuário que estabelece a conexão com o banco de dados. O ideal é que as permissões de acesso deste usuário estejam restritamente limitadas às funções que irá realizar, ou seja, para a exibição de um relatório, a conexão com o banco de dados deve ser realizada por um usuário com permissões de leitura e acesso somente às tabelas necessárias para sua operação.

Todos os valores originados da coleta de dados externos, devem ser validadas e tratadas a fim de impedir a execução de eventuais instruções destrutivas ou operações que não sejam as esperadas.

Um tratamento básico para a execução de querys com variáveis contendo valores informados pelo usuário:

Com a utilização da função addslashes() será adicionada uma barra invertida antes de cada aspa simples e aspa dupla encontrada, processo conhecido como escape. Se a diretiva de configuração do PHP magic_quotes_gpc estiver ativada, o escape é realizado automaticamente sobre os dados de COOKIES e dados recebidos através dos métodos GET e POST. Neste caso, não deve ser efetuado o tratamento com addslashes(). A função get_magic_quotes_gpc(), disponível nas versões do PHP a partir da 3.0.6, retorna a configuração atual da diretiva magic_quotes_gpc.

Abaixo, a query string resultante da aplicação do tratamento mencionado:

Em muitos bancos de dados, existem funções específicas para o tratamento de variáveis em query strings, o que diminui a compatibilidade do código fonte para operação com outros sistemas de banco de dados.

Outra dica importante é evitar a exibição das mensagem de erro em um servidor de aplicação em produção, pois geralmente nos erros ou alertas são exibidos caminhos de diretórios do sistema de arquivos e informações à respeito do esquema do banco de dados, podendo comprometer a segurança do sistema.

Para ocultar a exibição de erros e alertas do PHP, é necessária a configuração da diretiva display_errors para Off no arquivo de configurações do PHP.

Cabe ao desenvolvedor estar atento às possíveis brechas de segurança existentes nos códigos fonte que produz, principalmente quando o que está em jogo é um bem de grande valia: a informação. Tenha consciência. Isto evita futuras dores de cabeça e atritos desnecessários com o cliente.


Comente também

36 Comentários

Diego A. Griep
Diego A. Griep

Já conhecia o assunto, mas é sempre bom ler a visão de outras pessoas, é bom se proteGer do sql injection.

* Dica:
Quando for postar um artigo, tenha sempre um dicionário ao lado.

[ ]'s

Perneta
Perneta

seu boco de teta... nada disso funcionou... os cara invadiram o negocio.... viram tudo meus registro... apagaram... bagunçaram... e eu tinha esses codigo tudo ai... ou seja... se o cara sabe.... ou melhor... se o cara nao sabe... mas usa um programa chamado SQL INJECTION FREE ele consegue fazer passar por tudo esses treco ai de vocês... e essa merda ainda nao deixa comentar....

Rafael Capucho
Rafael Capucho

Eu gostaria de saber se assim também é possivel um Injection: WHERE senha = '".$senha."'; espero respostas, Obrigado.

Luis Fernando D. Andrade
Luis Fernando D. Andrade

Ola, gostei da sua materia e parabens pela iniciativa de falar sobre seguranca embora que bem superficialmente ;).
Uma funcao muito boa 'anti sql injection' foi criada pelo Fabyo, aqui:
http://forum.imasters.com.br/index.php?showtopic=125349&hl=sql injection

Parabens e que voce continue abordando temas relacionados a essa materia.
[]s
Luis

Igor Escobar
Igor Escobar

Tem gente que gosta de voltar no tempo...

DANIEL MAFFIOLETTI
DANIEL MAFFIOLETTI

Sem dúvida que este assunto é importante para iniciantes. Existem vários métodos relacionados!

Cleison Pinter Baldin
Cleison Pinter Baldin

Outra forma de tratar o uso do SQL Injection, é obrigar o usuário a digitar login e senha, pois desta forma ninguem consegue submeter a pagina sem as dias informações.
Também utilizar criptografia na senha é muito interessante.

Ana Claudia Nogueira
Ana Claudia Nogueira

Muito legal a sua iniciativa de falar sobre sql injection, mas ficou um pouco resumido, poderia ter sido falado mais sobre outros modos de injection

Edu Oliveira
Edu Oliveira

Muito gata e entende de programação? Bom demais pra ser verdade rsrs

Tiago Vailati
Tiago Vailati

Pessoal, tudo certo? Como foi abordado no artigo, hoje em dia, o próprio PHP já possui tratamento para dados recebidos via POST, GET e Cookies. Logo, a utilização da SQL Injection tem sido bastante dificultada. O artigo visa explanar sobre o conceito e como a SQL Injection atua, por isso, foi tratada numa visão mais superficial.

Laércio Crestani
Laércio Crestani

Seria um pouco melhor um

<?
if(!isset($_POST['usuario']) || trim($_POST['usuario']) =='' || !isset($_POST['senha']) || trim ($_POST['senha'] =='')){

header('location:login.php');
exit;
}
else {
echo $_POST['usuario'];
echo $_POST['senha'];
};
?>

se chegar '' vazio, ele volta ai senão ele continua... um pouco mais lógico e ñ precisa dea verificação ON em magic_quotes_gpc no php.ini...

Anderson Cavalcante
Anderson Cavalcante

Boa a matéria,

São poucos os programadores que pensam na questão: "Segurança". Por isso tantas falhas.

Algo muito bom de utilizar, são as expressões regulares. Onde você especifica o que o campo poderá aceitar de caracter. Neste caso, entraria de a-z, A-Z, 0-9. Nada mais do que isso, dae não teria problema de substituir por contra barra para escapar o caracter. Por exemplo, posso utilizar o caracter #, que iria comentar o restante do código SQL ;)

Abraços

Thiago Ferreira
Thiago Ferreira

O artigo não trouxe nada de novo. Explicações manjadas da web. Acho que é preciso trazer alguma coisa realmente nova ou nem escrever nada.

Admir Tomaz
Admir Tomaz

Serve apenas para novatos, sendo que o perigo do injetion nem foi falado, o perigo é quando fica vulnerável a ter uma tabela toda deletada pelo "drop", até um "select" de uma busca mal programada pode gerar uma perda enorme de dados.

Érico Gustavo Kmetzsch
Érico Gustavo Kmetzsch

eu custumo usar a funcao do php htmlspecialchars() filtrando as variaveis que recebem valores do metodo POST ou GET

Kenneth Becker
Kenneth Becker

Nao sei se esta tecnica eh muito comum, mas eu costumo usar a funcao md5($str) para login. Ela transforma $str em uma chave criptografada.
Quando cadastro usuario, salvo no banco a senha criptografada. Como esta funcao nao permite volta (nao existe um desfaz_md5()), utiliza-se a funcao tambem na senha passada por post, na ocaisao do login.

Acredito que este procedimento evite o problema do injection.

Juliano dos Santos da Silva
Juliano dos Santos da Silva

Ae galera to gostanu até pq eu sou um novato msm na area e tento o melhor q eu posso nunca tem ninguem pra dar uma mãozinha sabem como é ¬¬

ae galera tipo se tive alguem a fim de me tirar uma duvida me add ae no msn: kcd_cs@hotmail.com

vlw gente fica cum DEUS

Tiago Gouvêa
Tiago Gouvêa

Outra maneira de "limitar" as entradas de dados é utilizando typecast, convertendo assim uma entrada obtida $_POST ou $_REQUEST em um tipo determinado.
Uma maneira é: $codigo=(int) $codigo;
Outra pode ser:
settype($codigo,integer);

Saudações

Leonardo Cesar Teixeira
Leonardo Cesar Teixeira

A função addslashes() é meio ultrapassada e eu não vejo porque em utilizada se tem uma função específica do PHP pra escapar aspas simples e duplas.

No caso de um simples login o addslashes() pode quebrar um galho, mas na caso de inserção de dados o addslashes() irá estragar os textos mandando eles pro banco de daodos com barras invertidas.

Então já que este site é uma das principais guias para os programadores do Brasil, eu não acho certo ensinar como evitar um problema de segurança utilizando o pior método.

A melhor função para evitar ataques de SQL Injection é usando a função mysql_real_escape_string(), ela irá escapar os dados apenas na hora da consulta e no banco de dados não irá ficar com as barras invertidas.

Eu fiz um artigo em meu blog explicando como se proteger de ataques de SQL Injection de forma eficaz e sem "destruir" os dados. E também tem um tutorialzinho ensinando a criar uma função para proteger seus scripts contra este ataque.

Para lêr o artigo acesse o endereço abaixo:

http://blog.portaldoleo.com/2007/08/28/como-evitar-ataques-de-sql-injection-no-php-e-mysql/

Mas esse artigo do Imasters está muito bom pras pessoas terem uma idéia de como ocorre um ataque de SQL Injection.

Abraços!

Maurício Reatto Duarte
Maurício Reatto Duarte

Nossa, eu tava tendo este problema, daí não lembrava mais como usar o anti sql-injection
Dai essa vlw ein !!

Moacir Fernandes
Moacir Fernandes

Pelo que percebi, você está dando o select validando o login e senha de escape, para que serve então o login e senha se não está sendo usado!

Daniel Neto
Daniel Neto

É um complemento do firefox que possibilita injetar codigo em qualquer campo do formulario, esta ferramenta é muito usada por hackers, a ferramenta pode ser baixada aqui: https://addons.mozilla.org/pt-PT/firefox/addon/6727

Leo Baiano
Leo Baiano

Concordo com o Leonardo, eu também acho que o mysql_real_escape_string() é uma solução mais atual e melhor para proteção contra sql injection.

Normalmente utilizo a seguinte função:

function anti_sql_injection($string){
$string = get_magic_quotes_gpc() ? stripslashes($string) : $string;
$string = function_exists("mysql_real_escape_string") ? mysql_real_escape_string($string) : mysql_escape_string($string);
return $string;
}

Jo?Jorge
Jo?Jorge

Olá leo, como utiliso essa função pra me proteger

thiago
thiago

duvido alguem derrubar meu banco.
dou 10000

João
João

Se ele está em um pc conectado à internet não é impossível. Por mais protegido que esteja, não é impossível......a não ser que esteja isolado.

Não é nada fácil, ainda mais hoje que os sistemas estão com a segurança cada vez mais elevanada, mas não impossível. Se ainda assim acredita que está imune, sinto muito mas você precisa atualizar seus conceitos.

Lohan
Lohan

eu gostei boa matéria!!!!!!

Marcus
Marcus

Prabéns pelo artigo.

Marcos Knijnik
Marcos Knijnik

Só para avisar que o addslashes apenas funciona caso estejamos falando de string. Porém, caso estejamos lidando com números, é uma outra história...

Por exemplo:

<?php
$id = $_GET['id']; // um número

$query = "SELECT * FROM tabela WHERE id=$id";
?>

Aí nem addslashes resolve. Imagina que o cara digite "DROP tabela". Aí lá se vai nossa querida tabela...rs

Para impedir Sql Injection com números, acho que isso basta:

<?php
$id = 0 + $_GET['id'];
?>

E isso é, aliáis, bem interessante, pois o PHP realiza essa conversão automaticamente (http://www.php.net/manual/pt_BR/language.types.string.php#language.types.string.conversion). Ou seja, ele irá adicionar 0 à id recebida. Caso esta seja "0 DROP tabela", ela excluirá tudo que segue um caracter não-numérico, no caso o espaço, e " DROP tabela" deixaria de existir...

Att.
Marcos Knijnik

Leonir
Leonir

Segue aqui um completinho, não fiz orientado a objetos:

$recebe = preg_replace(sql_regcase("/(from|select|insert|delete|where|drop table|show tables|update|declare|exec|set|cast|$|#|%|&|'|\"|`|;|\*|--|\\\\)/"),"",trim(addslashes(htmlspecialchars(strip_tags($_POST['recebe_formulario'])))));

isso foi perfeito para mim, limparam minha base de dados, depois tive de implantar esta segurança

Gstv.inc
Gstv.inc

aqui uma funcao simples
http://www.w3schools.com/PHP/func_mysql_real_escape_string.asp

<?php
function check_input($value)
{
// Stripslashes
if (get_magic_quotes_gpc())
{
$value = stripslashes($value);
}
// Quote if not a number se NAO FOR NUMERO
if (!is_numeric($value))
{
$value = "'" . mysql_real_escape_string($value) . "'";
}
return $value;
}

$con = mysql_connect("localhost", "peter", "abc123");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}

// Make a safe SQL
$user = check_input($_POST['user']);
$pwd = check_input($_POST['pwd']);
$sql = "SELECT * FROM users WHERE
user=$user AND password=$pwd";

mysql_query($sql);

mysql_close($con);

basta adicionar o check_input() com seu post dentro e ele faz o resto

espero ter ajudado

Victor Hugo Lopes
Victor Hugo Lopes

Bom post amigo,

Foi bem útil.

LOL
LOL

usem PDO.

Perneta
Perneta

seu boco de teta... nada disso funcionou... os cara invadiram o negocio.... viram tudo meus registro... apagaram... bagunçaram... e eu tinha esses codigo tudo ai... ou seja... se o cara sabe.... ou melhor... se o cara nao sabe... mas usa um programa chamado SQL INJECTION FREE ele consegue fazer passar por tudo esses treco ai de vocês... e essa merda ainda nao deixa comentar.... soh pq comentei num cara que falo a 4 anos... vo fala pra vc tbm que falo a 2 mêis

mario
mario

Motherboard view here: <a title="laptop driver" href="http://www.laptop-driver.net/">laptop driver</a> | <a href="http://mastertea.blogspot.com/">download driver</a> | <a href="http://mastertea.blogspot.com/2010/06/download-driver-ms-7525-ver-10.html">ms 7525</a>

Anderson
Anderson

Olá tiago, cara sou leigo em php eu saber se vc poderia por favor me ajudar com esse script que ta liberando acesso com 'or' 1 em login e senha ..desde já agardeço.




<?php
if ($acao == "validar_acesso"){
$sql="select * from usuario where (login='$edt_login') and (senha='$edt_senha')";
$exe=mysql_query($sql);
$num=mysql_num_rows($exe);
if ($num <=0){
echo "<script>window.alert('ERRO. Acesso nao permitido');</script>";
echo "<script>window.location='index.php';</script>";
} else {
$tmp=mysql_fetch_array($exe);
$usuario_situacao=$tmp[situacao];
if ($usuario_situacao == 0){
echo "<script>window.alert('ERRO. Login Inativo. Favor contactar o Administrador');</script>";
echo "<script>window.location='index.php';</script>";
}
if ($usuario_situacao == 9){
echo "<script>window.alert('ATENCAO. Login Bloqueado. Favor contactar o Administrador');</script>";
echo "<script>window.location='index.php';</script>";
}
if ($usuario_situacao == 1){
$_SESSION['acesso_idusuario']=$tmp[idusuario];
$_SESSION['acesso_idempresa']=$tmp[idempresa];
$_SESSION['acesso_admin']=$tmp[admin];
$_SESSION['acesso_revenda']=$tmp[revenda];
echo "<script>window.location='principal.php';</script>";



Qual a sua opinião?

Comentários considerados ofensivos serão moderados.
IBM

Parceiros

IBM
PagSeguro
Internet Innovation
Dialhost
HostNet
Tecla
KingHost
DotStore
Dinamize