Sql malicioso X PreparedStatement

10 respostas
lgr

Boas,
Sabemos que é possível,num login por exemplo, uma pessoa adicionar um “código” na caixa e que este texto quando somado à consulta sql irá resultar em algum problema, como por exemplo dropar uma tabela.
Além de prever essa segurança através de permissão a nivel de banco, se eu usar prepared statement fará diferença se não usar statment ?

OBS:Não sei se sabem do que estou falando,mas se souberem qual solução poderei estar adotando para evitar esses problemas?

grato

Leandro

10 Respostas

T

PreparedStatement reduz consideravelmente as chances de você ser vítima de um SQL malicioso, porque os dados String são enviados para o banco de forma que não interfiram na própria query (muitas vezes, dependendo do banco, a query nunca é montada como uma única string, mas sim serve apenas para localizar a consulta em um cache de consultas pré-preparadas; os dados em “?” são enviados em forma binária - RPC no caso do MS SQL Server - e não formam a string SQL.).
Por exemplo:

“SELECT * FROM TABELA WHERE CAMPO = ?” nunca vai dar o mesmo problema de:

String campo = "Josilene' ; DELETE FROM TABELA; COMMIT; --";
String sql = "SELECT * FROM TABELA WHERE CAMPO = '" + campo + "'";

Isso porque o comando com PreparedStatement irá interpretar a string apenas como uma string, não como um comando.

V

a montagem da string sql não muda no statement ou no prepared para o banco, a diferença é a nivel de codificação.

eu fiquei curioso de ver um bug desse em ação pois não conseguir imaginar algo em que ele funcionasse
uma tela de cadastro por exemplo teria o campo nome e email que seriam agregados ao meu insert clientes (nome, email) values (‘victor’,‘v@h’) ou um select da vida como acrescetar o meu drop table clientes e funcionar ?

V

é isso ai

T

victorhugomuniz:
a montagem da string sql não muda no statement ou no prepared para o banco, a diferença é a nivel de codificação.

Só se o driver for mal-codificado, ou o banco não aceitar comandos preparados.

Que eu saiba, se usar o PreparedStatement, a string SQL sequer é montada para a maior parte dos bancos (mas acho que o driver do MySQL para versões antigas do banco chega a montar a string. Mas isso é exceção);

é por isso que não existe um método que permita obter a string SQL que teria sido montada pelo PreparedStatement.

Mas o comando, em si, é corretamente executado pelo banco, e costuma ser mais rápido que mandar a string SQL inteira para ele processar. (Na primeira e segunda execuções, porque o banco têm de compilar o comando SQL, pode até ser que seja mais lento <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@14/assets/72x72/w.pngink.png?v=9" title=":wink:" class="emoji" alt=":wink:"> )
T

victorhugomuniz:
eu fiquei curioso de ver um bug desse em ação pois não conseguir imaginar algo em que ele funcionasse
uma tela de cadastro por exemplo teria o campo nome e email que seriam agregados ao meu insert clientes (nome, email) values (‘victor’,‘v@h’) ou um select da vida como acrescetar o meu drop table clientes e funcionar ?

Pois é.

String nome = "Hermengarda', '[email removido]'); UPDATE TBCLIENTES SET password = 'hack'; COMMIT; -- ";
String email = "[email removido]";
String sql = "INSERT CLIENTES (nome, email) VALUES ('" + nome + "','" + email + "')";

Se você fez tudo errado, você está usando um usuário com poderes administrativos para acessar o sistema. Então o cara pode até usar um “drop table”.

Prepared Statements procuram evitar esse tipo de problemas.

lgr

Mas,
e a solução pessoal?
Seria então a nivel de banco memso?
O usuario que uso para conectar “a tbl” deve ter permissão só de select,certo?
Não há outra solução.
Talvez ajude tb a seguinte gambiarra:

no código retirar as palavras drop,update e insert da string…rsssss
só se for…

L

Aí , Victor, só pra matar sua curiosidade.
Esse tipo de “ataque” é conhecido como injeção de SQL.
Vou te dar um exemplo de uma tela de login. Imagina que vc tem os campos usuário e senha no formulário.
O internauta preenche o campo usuário com o valor lixo’ or 1=1 /*.
Então o cara que está montando o sql na mão, juntaria tudo isso e uma string sql que ficaria assim:

Select * from usuario where username='lixo' or 1=1 /* and senha = '123456'

Percebeu que quando vc colocou o username como lixo’ or 1=1 /*, você alterou a forma de construção do SQL, que passou a procurar um usuário chamado lixo e adicionou uma clausula (1=1) que fará que todas as linhas da tabela sejam retornadas e depois disso adicionou um comentário que fará com que o restante do comando seja ignorado.

Se quiser saber mais sobre esse assunto, pesquise sobre SQL Injection.

T+

Léo

T

É bastante simples:
a) Usar apenas PreparedStatement, que evita esses problemas oriundos de não “escapar” os caracteres especiais contidos dentro de strings;
b) Usar um usuário no banco, para a sua aplicação, que não tenha poderes administrativos.
Isso já mata 99% dos problemas.

V

muitissimo obrigado

lgr

Opa.
obrigado tb…

Criado 22 de agosto de 2006
Ultima resposta 22 de ago. de 2006
Respostas 10
Participantes 4