Sobes.tech
Junior

Como prevenir injeções de SQL em bancos de dados?

sobes.tech IA

Resposta da IA

Para prevenir injeções SQL, aplicam-se as seguintes abordagens:

  1. Utilização de consultas parametrizadas (Prepared Statements): Este é o método principal e mais eficaz. Em vez de inserir valores diretamente na consulta, usam-se marcadores de posição (?), e os valores são passados separadamente. A base de dados distingue a estrutura da consulta e os dados, o que impede a execução de código malicioso.

    // Utilização de consulta parametrizada
    String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
    try (PreparedStatement stmt = connection.prepareStatement(sql)) {
        stmt.setString(1, username); // Primeiro valor para o primeiro marcador '?'
        stmt.setString(2, password); // Segundo valor para o segundo marcador '?'
        ResultSet rs = stmt.executeQuery();
        // Processamento de resultados
    } catch (SQLException e) {
        e.printStackTrace();
    }
    
  2. Escapamento de caracteres especiais: Este método é menos preferido em comparação com as consultas parametrizadas, mas pode ser usado como medida adicional ou em situações onde as consultas parametrizadas não sejam aplicáveis (por exemplo, ao formar nomes de tabelas/colunas dinâmicos, embora isso deva ser evitado). Os caracteres especiais SQL (por exemplo, ', ", \, %, _) devem ser escapados para que sejam interpretados como caracteres literais e não como parte da sintaxe SQL.

    // Exemplo (não recomendado para uso direto com entrada do usuário)
    // É melhor usar bibliotecas ou frameworks que façam isso de forma segura.
    String userInput = "O'Reilly";
    String escapedInput = userInput.replace("'", "''"); // Exemplo de escape simples de aspas simples
    String sql = "SELECT * FROM books WHERE author = '" + escapedInput + "'";
    
  3. Validação e filtragem da entrada do usuário: Verificação do tipo, formato e comprimento dos dados do usuário. Limpeza ou rejeição de entradas que contenham caracteres especiais ou formato incorreto.

    • Exemplo: Se for esperado um número, converta explicitamente a entrada para um tipo numérico.
    // Validação da entrada do usuário (exemplo)
    String idString = request.getParameter("id");
    try {
        int userId = Integer.parseInt(idString); // Conversão para número
        // Depois, use userId na consulta parametrizada
    } catch (NumberFormatException e) {
        // Tratamento de entrada incorreta (por exemplo, enviar erro ao usuário)
        System.err.println("Formato de ID incorreto: " + idString);
    }
    
  4. Utilização de frameworks ORM (Hibernate, JPA): A maioria dos frameworks ORM modernos usam por padrão consultas parametrizadas para operações padrão (CRUD), o que protege automaticamente contra injeções SQL.

    // Exemplo de uso de JPA/Hibernate
    EntityManager em = ...;
    Query query = em.createQuery("SELECT u FROM User u WHERE u.username = :username", User.class);
    query.setParameter("username", username);
    User user = (User) query.getSingleResult();
    
  5. Restrição de privilégios das contas de banco de dados: Cada conta de usuário da aplicação deve ter privilégios mínimos necessários para realizar suas funções. Por exemplo, a conta usada pela aplicação web não deve ter permissão para excluir ou modificar a estrutura das tabelas.

Seguir estes princípios, especialmente o uso de consultas parametrizadas, é fundamental para prevenir injeções SQL.