SQL Injection é uma técnica para obter dados ou acesso a aplicações que utilizam bancos de dados. Esta técnica utiliza a inserção de códigos SQL em formulários de páginas de Internet.
Ao inserir texto em campos como de nome de usuário ou senhas, ele geralmente é inserido em expressões SQL e checados em um banco de dados. O acesso à aplicação é concedido ou não, dependendo do resultado da execução da expressão SQL.
É comum que um teste deste tipo ocorra com uma instrução SQL como
SELECT * FROM Usuarios WHERE nome = 'nomedousuario' AND senha = 'senhadousuario'
Esta instruções só retornaria algum registro se a combinação de nome de usuário e senha combinar com os valores inseridos no banco de dados. O acesso seria concedido se algum registro retornasse ao se realizar esta consulta.
Imagine que alguém conseguisse executar uma instrução como
SELECT * FROM Usuarios WHERE nome = 'nomedousuario' AND senha = 'senhadousuario' OR 1=1
Neste caso todos os registros seriam retornados e o acesso seria concedido. O problema para forçar a execução desta instrução é o uso das aspas. Contudo, em uma instrução SQL, tudo o que vier após algum símbolo que indique comentário será ignorado. Dependendo do SGBD é possível utilizar símbolos como dois hífens (‘–’) ou o sustenido (‘#’) Então basta inserir uma aspa e uma instrução que sempre seja considerada como TRUE e os dois hífens para obter concessão de acesso. Por exemplo, ao digitar
' OR 1=1 --
como nome de usuário, a expressão SQL ficaria assim
SELECT * FROM Usuarios WHERE nome = '' OR 1=1 --' AND senha = 'senhadousuario'
concedendo acesso ao aplicativo sempre, sem nem mesmo precisar digitar a senha.
Outra forma de obter acesso é tentar passar como um usuário com acesso privilegiado, como ‘admin’. Entrar com
admin' --
no campo de nome de usuário deve ser suficiente para obter acesso aos sistemas e com privilégios de administrador! Este é um excelente motivo para você alterar o nome do usuário de administração padrão de sistemas adquiridos de terceiros ou de não usar contas de administração com nomes previsíveis.
Ataques mais destruidores podem ser executados em sistemas especialmente frágeis. Imagine que alguém digite em um formulário de login algo como
' OR 1=1 ; Drop table Usuarios --
Além da concessão de acesso o hacker conseguiria também remover uma tabela importante. Dependendo do sistema ele poderia tentar outros nomes de tabela como Clientes. Os ataques feitos sem pleno conhecimento da estrutura do banco de dados podem ser chamados também de Blind SQL Injection.
Veja que não comentamos aqui sobre a possibilidade de realizar SQL Injection diretamente na URL, mas estamos pressupondo que ao menos os desenvolvedores não utilizem o método GET em formulários de login.
Se quiser saber mais sobre técnicas simples de ataques na web, leia algo mais no CMS Wire ou no UnixWiz.
Soluções
Diversas soluções podem ser utilizadas para impedir um ataque por SQL Injection.
Uma delas é utilizar a função mysql_real_escape_string do PHP para tratar os caracteres especiais. Outra forma é o uso de Prepared Statements. O efeito é semelhante ao tratamento de caracteres especiais. O uso destas técnicas combinadas com a aplicação de Stored Procedures, pode aumentar ainda mais a segurança e desempenho de sua aplicação.
Teste
Vejamos um rápido tutorial de como realizar e proteger-se de um Blind SQL Injection.
Para testar a SQL Injection, criei um banco de dados “Teste” em MySQL com uma tabela “Usuarios” que contém dois campos: “Usuario” e “Senha”. Parece-nos familiar, não? O primeiro registro desta tabela é do usuário “admin” e senha “123456″. Foi inserido também o usuário “user” com senha “888888″.
A página “login.php” contém três formulários. O primeiro acessa uma página sem nenhum tipo de proteção. O segundo envia os dados para uma página que utiliza mysql_real_escape_string e o terceiro utiliza a técnica de Prepared Statements. A página “acesso.php” trata os dados enviados pela “login.php” de forma simples. A página “acesso2.php” utiliza a função de tratamento de caracteres especiais e “acesso3.php” utiliza Prepared Statements.
Digite
' OR 1=1 #
no campo de nome de usuário do login.php e veja como pode ser fácil acessar este “sistema”.
Outro teste pode ser feito digitando-se no mesmo campo
admin' #
Arquivos do teste podem ser obtidos clicando aqui..