SQL injection em dataset do Fluig: como evitar
Dataset do Fluig com SQL concatenado é uma porta aberta. Veja como usar PreparedStatement, proteger JDBC, limitar acessos e revisar seus datasets.
Datasets com JDBC são uma forma poderosa de consultar bancos no Fluig. Também são um risco pouco discutido, porque um dataset não é uma tela protegida: ele é uma API. Qualquer usuário logado com acesso à plataforma pode tentar chamá-lo com os parâmetros que quiser.
Por isso, a validação no formulário não protege o dataset. Quem barra caracteres só no navegador não barrou nada.
O erro: montar SQL por concatenação
// Nao faca isso
var sql = "SELECT * FROM CLIENTES WHERE NOME LIKE '%" + termo + "%'";
var rs = stmt.executeQuery(sql);
Basta um apóstrofo no valor para a instrução quebrar, inclusive em um nome legítimo como D'Ávila. E o mesmo espaço que quebra a consulta pode ser usado para mudar o que ela faz.
Em datasets que também gravam, o risco é maior: um mesmo script que cuida de inserir, alterar e excluir, recebendo operação e valores por constraint, pode virar uma forma de alterar dados diretamente.
A correção: PreparedStatement
function buscarClientes(termo) {
var conexao = null;
var stmt = null;
var rs = null;
try {
var contexto = new javax.naming.InitialContext();
var fonte = contexto.lookup("/jdbc/MeuDatasource");
conexao = fonte.getConnection();
stmt = conexao.prepareStatement("SELECT CODIGO, NOME FROM CLIENTES WHERE NOME LIKE ?");
stmt.setString(1, "%" + termo + "%");
rs = stmt.executeQuery();
// Leia o resultado aqui
} finally {
if (rs != null) rs.close();
if (stmt != null) stmt.close();
if (conexao != null) conexao.close();
}
}
Dois ganhos: o valor nunca é interpretado como SQL, e o finally garante o fechamento da conexão. Conexão esquecida é outra causa clássica de problemas no pool.
Nomes de tabela e coluna não entram como parâmetro. Se eles precisam variar, use uma lista fixa no código:
var colunas = { "nome": "NOME", "codigo": "CODIGO" };
var coluna = colunas[campoRecebido];
if (!coluna) {
throw "Campo de ordenacao invalido";
}
Outras regras de segurança
Nunca execute SQL vindo do cliente. Um dataset "genérico", que recebe a consulta como parâmetro, entrega o banco a quem chamar. Parece prático para relatórios, mas não vale o risco.
Não aceite datasource por parâmetro. O nome do JNDI deve estar fixo no código.
Use conexões com o mínimo de permissão. Dataset de leitura usa um usuário de leitura. Assim, mesmo um erro no código tem alcance limitado.
Despublique o que era temporário. Datasets de carga, diagnóstico e correção não deveriam ficar disponíveis depois do uso.
Não exponha credenciais. Tabelas de configuração de serviços podem guardar tokens e dados de autenticação. Nunca devolva essas colunas em dataset, log ou widget.
Cuidado com dados sensíveis. Se a informação é restrita, verifique quem é o usuário dentro do dataset, em vez de confiar na tela que o chama.
Trate o erro sem contar demais. Registre o detalhe no log e devolva uma mensagem simples.
Como revisar os datasets que você já tem
Em acervos Fluig que acompanhamos, uma parte relevante dos datasets acessa banco diretamente. Vale um passe de revisão:
- Liste os datasets com
InitialContextougetConnection. - Procure
executeQuery(eexecuteUpdate(com concatenação por+. - Marque primeiro os que gravam dados ou recebem texto livre.
- Verifique se as conexões têm permissão de escrita sem necessidade.
- Identifique os datasets que ninguém mais usa e despublique.
- Confira se há conexões sem fechamento em
finally.
Se o dataset for usado em um campo zoom, lembre que o texto digitado também chega como constraint. Veja o guia de campo zoom no Fluig.
E quanto ao desempenho?
PreparedStatement costuma ajudar também, porque o banco reaproveita o plano de execução. Em consultas com LIKE '%termo%', porém, o índice não ajuda muito, então limite resultados com TOP ou LIMIT e exija um termo mínimo.
Perguntas frequentes
Dataset do Fluig pode ser chamado por qualquer usuário?
Datasets podem ser consumidos por usuários autenticados pelas APIs da plataforma. Por isso, não trate um dataset como se só a sua tela pudesse chamá-lo. Confira as permissões no seu ambiente.
Validar no formulário não basta?
Não. A validação no navegador é conveniência. A proteção precisa estar no servidor.
Devo evitar JDBC em datasets?
Não necessariamente. Quando há uma API do ERP, ela costuma ser a melhor opção. Quando JDBC é o caminho certo, use conexão de leitura e parâmetros.
Quer saber como estão os seus datasets? A consultoria Fluig da MyQube revisa customizações e aponta o que precisa de atenção primeiro. Vamos conversar.
Sua operação ainda depende de planilhas e retrabalho?
Agende uma conversa gratuita e receba um diagnóstico inicial dos seus gargalos operacionais.
Falar com a MyQubeOu conheça nosso serviço de Consultoria Fluig