Injeção SQL: nunca cole texto do usuário numa consulta
As consultas neste site você digita de propósito. Num aplicativo, parte do texto de uma consulta vem de um formulário, uma URL ou uma API. Se esse texto for colado no SQL, um visitante pode mudar o que a instrução faz. Esta página mostra o erro no banco da padaria e depois a correção. Não é um guia para atacar outros sistemas.
A consulta que você queria
Suponha que um app busque um cliente pelo sobrenome. O SQL pretendido filtra só esse nome.
SELECT first_name, last_name FROM customers WHERE last_name = 'Lopez' ORDER BY customer_id;
Resultado: Ana Lopez, uma linha.
O que o texto colado pode fazer
Se o app monta a instrução como `WHERE last_name = '` mais o que o visitante digitou mais `'`, então colocar SQL extra nessa string muda o filtro.
A consulta abaixo é a mesma instrução depois que alguém digita um sobrenome que não fecha as aspas e acrescenta `OR 1 = 1`. `1 = 1` é sempre verdadeiro, então o WHERE não restringe mais as linhas. O mesmo tipo de erro em UPDATE ou DELETE sem um WHERE apertado pode alterar ou remover cada linha.
SELECT first_name, last_name FROM customers WHERE last_name = 'Lopez' OR 1 = 1 ORDER BY customer_id;
Resultado: Os oito clientes. O filtro do nome não limita mais o resultado.
A correção: parâmetros vinculados
Não junte texto do usuário ao SQL. Envie a instrução com um placeholder e passe o valor à parte. PostgreSQL usa `$1`, `$2`, e assim por diante. O banco trata o valor como dado, nunca como sintaxe, então um sobrenome que parece SQL continua um sobrenome.
A consulta que você escreve é então sempre `WHERE last_name = $1`. Bibliotecas e ORMs chamam isso de consulta parametrizada ou prepared statement. Você ainda precisa usar: um ORM que concatena strings tem o mesmo erro.
SELECT first_name, last_name FROM customers WHERE last_name = 'Lopez' ORDER BY customer_id;
Resultado: Ana Lopez de novo: a busca com um valor vinculado, mostrada aqui com um literal porque este editor não tem camada de aplicativo.
Perguntas comuns
- Bastam aspas a mais em volta do valor?
- Não. Esquecem um escape, as codificações diferem e números não vão entre aspas. Parâmetros vinculados evitam essa classe inteira de erros.
- Um ORM quer dizer que posso ignorar isso?
- Só se cada consulta passar pela API de parâmetros. Strings SQL cruas dentro de um ORM ainda são SQL concatenado. Prefira o query builder ou `execute(sql, [value])`.
- E UPDATE e DELETE?
- A mesma regra: o WHERE deve usar parâmetros, nunca texto colado. Um WHERE ausente ou quebrado nessas instruções muda uma tabela inteira de uma vez.