Posted by Leonardo Wed, 08 Aug 2007 03:33:22 GMT
SQL Injection é um problema comum de ocorrer se não tivermos cuidado com as informações vindas dos usuários, geralmente através de formulários. Um usuário malicioso poderia, por exemplo, tentar ter acesso a um cadastro manipulando o formulário de login de uma aplicação.
A seguir, criarei um cenário de login onde as informações vindas do formulário poderão ser manipuladas para ganhar acesso a aplicação, e depois, mostrarei como podemos evitar essa falha.
Este poderia ser um controller de autorização:
class User < ActiveRecord::Base
def login
@user = User.find(:first,
:conditions => "login = '#{params[:name]}'
AND password = '#{params[:password]}'")
end
end
Isso é perigoso porque o símbolo # substitui a váriável diretamente pelo valor, sem nenhum tratamento. Então, se um usuário entrasse com o seguinte nome e senha:
params[:name] = ' OR '1'='1
params[:password] = ' OR '1'='1
geraria esta consulta no banco:
select * from users where login='' OR '1'='1' AND
password='' OR '1'='1' LIMIT 1
Com essa consulta, o usuário entraria no site com o login do primeiro usuário cadastrado no banco. Como a cláusula OR sempre será true, é como se fizéssemos o select sem cláusula where e isto retornaria a tabela inteira, mas com o LIMIT 1, apenas o primeiro usuário será retornado. Muitas vezes esse usuário pode ser até o administrador.
Para resolver essa falha, reescreveremos o método de login assim:
def login
@user = User.find(:first,
:conditions => ["login = ? AND password = ?"
,params[:name],params[:password]])
end
Veja que agora passamos a condição via array sendo o primeiro índice a condição propriamente dita e, a partir do segundo índice, as variáveis, já tratadas pelo Rails, que serão substituídas pelo símbolo ? na mesma ordem que os símbolos aparecem.
Com isso, podemos entrar com aqueles valores anteriores que não haverá problemas, pois os caracteres especiais foram tratados.
