SQL Injection no desenvolvimento móvel: o que é, métodos de ataque e proteção

Autor: IT Sectr Publicado: 2026-04-06 Tempo de leitura: 9 min

SQL Injection é um tipo de ataque à base de dados de uma aplicação onde um atacante injeta código SQL malicioso nos parâmetros da consulta, obtendo acesso não autorizado aos dados ou a possibilidade de os modificar. Segundo a OWASP (2025), a SQL Injection continua a ser uma das vulnerabilidades críticas capaz de levar a um compromisso total da base de dados. Injeção de código SQL permite ao atacante ler, modificar e apagar registos e, em alguns casos, obter acesso ao sistema operativo do servidor.

Pontos principais

  • SQL Injection — injeção de código SQL através de parâmetros do utilizador, alterando a lógica da consulta à base de dados
  • Parametrização de consultas — o principal método de proteção: separar o código SQL dos dados usando prepared statements
  • Tipos de ataques — injeção clássica (através de WHERE), Blind SQLi (inferências lógicas), UNION-based (leitura de outras tabelas)
  • Error-based SQLi — extração de dados através de mensagens de erro da base de dados
  • Frameworks ORM — reduzem o risco de SQLi quando usados corretamente, mas não o eliminam completamente

O que é SQL Injection?

SQL Injection é uma vulnerabilidade que ocorre quando uma aplicação constrói consultas SQL através de concatenação de strings com dados do utilizador. Um atacante passa uma string especialmente concebida num parâmetro de consulta que altera a estrutura do comando SQL. Em vez de serem dados, a string injetada torna-se parte do código SQL, permitindo ao atacante executar consultas arbitrárias contra a base de dados. Segundo o Relatório de Violações de Dados da Verizon (2025), a SQL Injection está presente em 8% de todas as violações de dados investigadas.

Porque é que a SQL Injection ainda é relevante?

Apesar de ser uma vulnerabilidade conhecida (mencionada pela primeira vez no final dos anos 90), a SQL Injection ainda é encontrada em aplicações modernas. A razão é o erro humano: os programadores escrevem código com concatenação de strings, o código legado não é refatorado e os frameworks ORM são usados incorretamente (por exemplo, consultas raw com interpolação de strings). Segundo a Veracode (2026), cerca de 14% de todas as aplicações analisadas contêm pelo menos uma vulnerabilidade SQLi.

O que pode fazer um atacante?

Uma injeção SQL bem-sucedida dá ao atacante uma vasta gama de capacidades: ler qualquer tabela da base de dados, incluindo hashes de palavras-passe e dados pessoais dos utilizadores; modificar e apagar registos; executar operações administrativas (DROP TABLE, TRUNCATE); e, em algumas configurações, execução remota de comandos através de xp_cmdshell (MSSQL) ou INTO OUTFILE (MySQL). As consequências vão desde a fuga de dados do utilizador até à perda total de controlo do sistema.

Tipos de injeções SQL

As injeções SQL são classificadas pela forma como os dados são extraídos da base de dados. A escolha do método depende de como a aplicação processa os resultados das consultas e as mensagens de erro. A classificação OWASP identifica três tipos principais: In-band (dados extraídos através do mesmo canal), Inferential/Blind (inferências lógicas) e Out-of-band (dados transmitidos através de outro canal).

TipoMétodo de extraçãoComplexidadeFrequência
In-band (clássico)Diretamente através do resultado da consultaBaixaAlta
Blind SQLiInferências lógicas a partir de respostas do servidorAltaMédia
Out-of-bandAtravés de um canal externo (DNS, HTTP)MédiaBaixa

In-band SQL Injection (Clássica)

O tipo mais comum. Um atacante injeta código SQL num parâmetro de consulta, e o resultado da injeção é diretamente visível na resposta do servidor. Dois subtipos: Error-based (através de mensagens de erro da BD) e UNION-based (através do operador UNION SELECT). Error-based utiliza informações de mensagens de erro, como um erro de sintaxe do MySQL que pode revelar o nome da tabela ou a estrutura da consulta. UNION-based permite combinar resultados de consultas legítimas com dados de outras tabelas da base de dados.

Blind SQL Injection (Cega)

Utilizada quando a aplicação não mostra os resultados da consulta nem as mensagens de erro. Um atacante faz perguntas de sim/não enviando consultas com condições lógicas e analisando as diferenças nas respostas do servidor (por exemplo, tempo de resposta ou conteúdo da página). Time-based Blind SQLi utiliza funções de atraso (SLEEP, WAITFOR DELAY) para confirmar condições — se a página demorar mais a carregar, a condição é verdadeira. Este método é muito lento — extrair um único registo pode levar horas.

python
# Exemplo de Blind SQL Injection (baseada em tempo)
# Se SQLi for vulnerável, SLEEP(2) executa se a condição for cumprida
import requests
import time

payload = "' OR IF(SUBSTRING((SELECT password FROM users LIMIT 1),1,1)='a',SLEEP(2),0) -- "
url = "http://example.com/user?id=1" + payload

start = time.time()
response = requests.get(url)
elapsed = time.time() - start

# Se a resposta chegar após >2 segundos — a primeira letra da palavra-passe é 'a'
print(f"Time: {elapsed:.2f}s - First letter is 'a'" if elapsed > 2 else "First letter is not 'a'")

Out-of-band SQL Injection

Os dados são transmitidos não através da resposta HTTP mas através de canais alternativos: consultas DNS, pedidos HTTP para um servidor externo, SMTP. Utilizada quando a aplicação não devolve resultados de consultas nem mostra erros. O MySQL suporta a função LOAD_FILE(), que pode iniciar uma consulta DNS, e o MSSQL tem xp_dirtree para enviar dados para um servidor SMB remoto. Out-of-band SQL Injection é eficaz mas requer configuração adicional do servidor atacante e funções específicas da BD.

Como funciona a injeção SQL?

O mecanismo da SQL Injection baseia-se no facto de o SQL utilizar aspas para literais de string. Se uma aplicação inserir a entrada do utilizador diretamente numa consulta SQL sem a escapar, um atacante pode “fechar” a string e adicionar código SQL arbitrário. Por exemplo, na consulta SELECT * FROM users WHERE name = '$input', inserir ' OR '1'='1 transforma-a em SELECT * FROM users WHERE name = '' OR '1'='1', que devolve todos os utilizadores.

Exemplo clássico: Evasão de autenticação

Considere um formulário de início de sessão com a consulta SELECT * FROM users WHERE username = '$user' AND password = '$pass'. Se um atacante introduzir admin' -- no campo de utilizador e deixar a palavra-passe em branco, a consulta resultante torna-se SELECT * FROM users WHERE username = 'admin' -- ' AND password = ''. Os caracteres -- comentam o resto da consulta, desativando a verificação da palavra-passe. O servidor devolve o registo do utilizador admin, e o atacante inicia sessão sem conhecer a palavra-passe.

python
# Exemplo de SQL Injection — Evasão de autenticação
# CÓDIGO VULNERÁVEL: concatenação direta de strings
def login_vulnerable(username, password):
    query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
    cursor.execute(query)
    return cursor.fetchone() is not None

# username = "admin' --" anula a verificação da palavra-passe
# VERSÃO SEGURA: consulta parametrizada
def login_secure(username, password):
    query = "SELECT * FROM users WHERE username = %s AND password = %s"
    cursor.execute(query, (username, password))
    return cursor.fetchone() is not None

UNION-based: Leitura de outras tabelas

O operador UNION SELECT permite combinar resultados de duas consultas SELECT. Se um atacante encontrar um parâmetro vulnerável, adiciona UNION SELECT com uma consulta de outra tabela. Por exemplo: ' UNION SELECT username, password FROM admins --. A condição de sucesso é que o número de colunas em ambas as consultas deve coincidir. O número de colunas é determinado através de ORDER BY (inserindo ' ORDER BY 1--, depois 2, 3... até ocorrer um erro). Conhecendo o número de colunas, o atacante insere UNION SELECT com o mesmo número de campos.

SQL Injection em aplicações móveis

As aplicações móveis enfrentam SQL Injection tanto no lado do servidor (API) como no lado do cliente — em bases de dados locais (SQLite, Realm). Embora a SQLi do lado do servidor nas APIs móveis seja semelhante às aplicações web, as bases de dados locais criam um vetor adicional. Se uma aplicação armazena dados em SQLite e executa consultas com concatenação de strings, os dados maliciosos que entram na base de dados local através da API podem desencadear SQLi durante o processamento posterior.

SQL Injection em SQLite no Android/iOS

A base de dados local SQLite num dispositivo também é vulnerável a SQL Injection se a aplicação construir consultas concatenando strings. Os Content Providers no Android e o Core Data no iOS utilizam parametrização por defeito, mas as consultas raw requerem atenção do programador. O SQLite não suporta múltiplas consultas separadas por ponto e vírgula, o que limita as opções do atacante mas não protege contra a leitura de dados através de condições WHERE. Utilize sempre selectionArgs no Android e NSPredicate com parâmetros no iOS.

SQL Injection através da API da aplicação móvel

A API com a qual uma aplicação móvel comunica é vulnerável como qualquer servidor web. Os programadores móveis muitas vezes assumem que a SQLi é apenas um problema do backend, mas a vulnerabilidade ocorre no endpoint da API que aceita parâmetros do cliente. A separação de responsabilidades não protege: se o programador do backend se esqueceu de parametrizar a consulta, a aplicação móvel do utilizador torna-se um vetor de ataque. Exija ao backend que utilize ORM ou prepared statements.

kotlin
// Exemplo de SQL Injection em SQLite local no Android
// CÓDIGO VULNERÁVEL: concatenação direta
fun getUserVulnerable(db: SQLiteDatabase, userId: String): Cursor {
    return db.rawQuery(
        "SELECT * FROM users WHERE id = $userId", null
    )
}

// VERSÃO SEGURA: parametrização através de selectionArgs
fun getUserSecure(db: SQLiteDatabase, userId: String): Cursor {
    return db.rawQuery(
        "SELECT * FROM users WHERE id = ?",
        arrayOf(userId)
    )
}

Métodos de prevenção de SQL Injection

A proteção contra SQL Injection baseia-se num princípio simples: nunca confie na entrada do utilizador em consultas SQL. O único método fiável é a parametrização de consultas (prepared statements), onde o código SQL e os dados são passados separadamente. Todos os outros métodos — escaping, validação, WAF — são camadas de segurança adicionais mas não substituem a parametrização. Segundo a OWASP (2025), a parametrização previne 100% dos ataques de SQL Injection.

Prepared Statements (Consultas parametrizadas)

Ao usar prepared statements, a consulta SQL é primeiro compilada pelo servidor de BD sem dados, e depois os valores dos parâmetros são passados separadamente. A base de dados trata os parâmetros como dados, não como código executável. Mesmo que um atacante passe ' OR '1'='1, a base de dados interpreta-o como um valor de string, não como código SQL. Os prepared statements são suportados por todas as linguagens e frameworks modernos: PDO em PHP, PreparedStatement em Java, cursor.execute em Python.

Frameworks ORM e Query Builders

Os ORM modernos (Hibernate, Entity Framework, SQLAlchemy, Room) utilizam automaticamente a parametrização ao executar consultas, a menos que o programador mude para consultas raw. No entanto, os ORM não protegem completamente: construções como @Query(value = "SELECT * FROM users WHERE name = :name", nativeQuery = true) em JPA requerem a passagem de parâmetros através de parâmetros nomeados, não por concatenação. Os Query Builders (Knex, jOOQ) também parametrizam as consultas por defeito se não forem usados métodos raw.

Escaping de strings (não recomendado como método principal)

O escaping de caracteres especiais (mysql_real_escape_string) é um método obsoleto que não protege contra todos os tipos de SQL Injection. O problema: o escaping depende da codificação e pode ser contornado ao usar codificações multibyte (por exemplo, GBK em sistemas asiáticos). Use o escaping apenas em código legado onde a parametrização é impossível, e sempre em combinação com uma validação rigorosa do tipo de dados de entrada.

MétodoEficáciaRecomendação
Prepared Statements100%Obrigatório para todas as consultas
ORM (uso correto)99%Recomendado
Escaping de strings70% (depende da codificação)Apenas legado
Validação de entrada (white-list)50% (apenas números)Adicional
WAF (Web Application Firewall)60%Adicional

Princípio do menor privilégio para a BD

A conta da aplicação deve ter os privilégios mínimos necessários: SELECT, INSERT, UPDATE, DELETE — apenas nas tabelas que a aplicação realmente necessita. Proíba o uso de DROP, TRUNCATE, CREATE para a conta da aplicação. Isto limita os danos mesmo em caso de uma injeção SQL bem-sucedida: o atacante não conseguirá eliminar tabelas nem executar operações administrativas.

Ferramentas para detetar injeções SQL

Os testes regulares de SQL Injection devem fazer parte do pipeline de desenvolvimento seguro. Uma combinação de análise estática, análise dinâmica e testes de penetração manuais oferece os melhores resultados. Segundo o Relatório de Cibersegurança da Synopsys (2025), os scanners automatizados encontram até 70% das vulnerabilidades SQLi, mas os ataques Blind complexos requerem testes manuais.

  • sqlmap — a ferramenta mais popular para deteção e exploração automática de SQL Injection
  • OWASP ZAP — um scanner DAST gratuito com módulos de análise ativa de SQLi
  • Burp Suite Scanner — uma ferramenta profissional com deteção automática de SQL Injection
  • SonarQube — análise estática de código para vulnerabilidades, incluindo padrões SQLi
  • CodeQL — análise semântica de código para encontrar injeções SQL no código fonte

Para aplicações móveis, a análise de SQLite local também é importante: verifique todas as chamadas rawQuery, consultas ContentProvider e consultas Room com rawQuery. Ferramentas: Android Studio Lint (deteta SQLi em SQLite), MobSF (Mobile Security Framework) para análise estática e dinâmica automática de APK/IPA. Recomenda-se também testar os endpoints da API através de sqlmap com interceção de proxy do tráfego da aplicação móvel.

Perguntas frequentes

Qual é a diferença entre SQL Injection e NoSQL Injection?

SQL Injection ataca bases de dados relacionais através de consultas SQL. NoSQL Injection afeta bases de dados não relacionais (MongoDB, Couchbase) através dos seus operadores de consulta ($gte, $ne, $where). No MongoDB, a injeção é possível se a aplicação construir um documento BSON a partir de uma string JSON. Os mecanismos de proteção são semelhantes: parametrização e validação de tipos.

Como detetar SQL Injection no código por conta própria?

Encontre todos os locais onde as consultas SQL são formadas por concatenação de strings com dados do utilizador. Procure padrões como "SELECT ... WHERE id = " + userId ou f"UPDATE ... SET name = '{name}'". Cada linha deste tipo é uma potencial injeção SQL. Substitua-as todas por consultas parametrizadas ou prepared statements.

O ORM protege automaticamente contra SQL Injection?

Os frameworks ORM protegem automaticamente apenas se utilizar os seus métodos Query Builder e parâmetros nomeados. Se utilizar consultas raw (nativeQuery em JPA, rawQuery em Room), a proteção não funciona — tem de passar os parâmetros através de expressões preparadas, não por concatenação de strings.

O que é Second-Order SQL Injection?

Second-Order SQL Injection é um ataque onde dados maliciosos são armazenados na base de dados como seguros, mas depois são utilizados noutra consulta sem escaping. Por exemplo, um atacante regista-se com um nome de utilizador como ' OR '1'='1. Os dados são guardados como uma string — não há ataque no registo. Mas se outra consulta utilizar o nome de utilizador em SQL sem parametrização, a injeção é ativada.

Pode NoSQL Injection ser mais perigoso que SQL Injection?

NoSQL Injection pode ser potencialmente mais perigoso devido à menor consciencialização dos programadores. Os programadores conhecem SQL Injection e a maioria usa ORM, mas poucos conhecem NoSQL Injection. No MongoDB, uma consulta mal formada pode devolver todos os documentos de uma coleção. A proteção é a mesma — prepared statements (parametrização BSON) e validação rigorosa de entrada.

Resumo

  • SQL Injection — um ataque que injeta código SQL através de parâmetros de utilizador não escapados em consultas à BD
  • Tipos principais — In-band (clássica), Blind (cega, baseada em tempo), Out-of-band (através de canal externo)
  • Parametrização de consultas — o único método 100% fiável de proteção contra SQL Injection
  • Mito do ORM — o ORM protege apenas quando usa métodos integrados; consultas raw com concatenação continuam vulneráveis
  • Princípio do menor privilégio — restringir os privilégios da conta de BD minimiza os danos em caso de ataque bem-sucedido
  • Testes regulares — sqlmap, OWASP ZAP, SonarQube devem fazer parte do pipeline CI/CD
  • SQLite local — as aplicações móveis também devem parametrizar as consultas à base de dados local

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também