Introdução
A injeção de SQL (SQL Injection) é uma técnica de ataque cibernético que explora vulnerabilidades na maneira como as aplicações interagem com bancos de dados SQL.
Atacantes mal-intencionados podem inserir código SQL malicioso em campos de entrada (por exemplo, formulários de login, barras de pesquisa) para modificar as consultas SQL executadas pela aplicação.
Cenário Vulnerável
Considere o seguinte trecho de código Java:
String query = "SELECT * FROM usuarios WHERE username = '" + username + "' AND password = '" + password + "'";Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery(query);var query = "SELECT * FROM usuarios WHERE username = '" + username + "' AND password = '" + password + "'";SqlCommand command = connection.CreateCommand();command.CommandText = query;connection.Open();SqlDataReader rdr = command.ExecuteReader();Um usuário normal enviaria credenciais corretas, tais como bob e M1nh@S3nha, que geraria o seguinte SQL:
SELECT * FROM usuarios WHERE username = 'bob' AND password = '<hash-da-senha>'Um atacante poderia enviar no campo username o valor bob' --, que geraria o seguinte SQL:
SELECT * FROM usuarios WHERE username = 'bob' --' AND password = '<hash-da-senha>'Forçando a consulta a não executar a verificação com o campo password, retornando o usuário bob mesmo sem sua senha.
Riscos
Qualquer consulta ao banco de dados que concatene um valor enviado pelo usuário pode estar vulnerável a este ataque.
Um atacante pode enviar parâmetros SQL que visem:
- Alterar campos indevidos (manipulando a instrução SQL para incluir um outro campo ou afetando outro usuário).
- Executar instruções de
UNION JOINe assim conseguir ler outras tabelas do banco de dados, podendo causar vazamento de dados. - Modificar a estrutura do banco a ponto de comprometer o funcionamento da aplicação, deixando-a fora do ar.
- Executar instruções de
DELETEouDROP, eliminando os dados de produção.
Como Corrigir
Ao realizar consultas no banco de dados, SEMPRE utilizar sql parameters. Cada linguagem possui sua forma correta de aplicar esta sanitização, pesquise por "Prevent SQL Injection + Sua Linguagem ou Framework".
String nomeUsuario = request.getParameter("username");String senha = request.getParameter("password");senha = PasswordHelper.hash(senha)
String query = "SELECT * FROM usuarios WHERE username = '" + nomeUsuario + "' AND password = '" + senha + "'"; Statement statement = connection.createStatement(); String query = "SELECT * FROM usuarios WHERE username = ? AND password = ?"; PreparedStatement statement = connection.prepareStatement(query); statement.setString(1, nomeUsuario); statement.setString(2, senha);ResultSet resultSet = statement.executeQuery();var query = "SELECT * FROM usuarios WHERE username = '"+username+"' AND password = '"+password+"'";var query = "SELECT * FROM usuarios WHERE username = @username AND password = @password";SqlCommand command = connection.CreateCommand();command.CommandText = query;command.Parameters.AddWithValue("@username", username);command.Parameters.AddWithValue("@password", password);connection.Open();SqlDataReader rdr = command.ExecuteReader();