SQL Injection¶
OWASP A03:2021 (Injection). A vulnerabilidade mais antiga e ainda mais explorada da web.
Como acontece¶
Concatenação de input do usuário em query SQL:
# VULNERÁVEL
@app.route("/search")
def search():
name = request.args.get("name")
cursor.execute(f"SELECT * FROM users WHERE name='{name}'")
Input ' OR '1'='1 retorna todos os usuários. Input '; DROP TABLE users; -- apaga a tabela.
Padrão seguro (parametrização)¶
# SEGURO
@app.route("/search")
def search():
name = request.args.get("name")
cursor.execute("SELECT * FROM users WHERE name = %s", (name,))
O driver do banco escapa o valor antes de enviar. Input malicioso vira string literal, sem efeito.
Variantes em outras linguagens¶
Por que eval SQL acontece tanto¶
ORMs amenizam o problema, mas em "queries cruas" (raw queries) o desenvolvedor volta a concatenar. Pesquisas tipo "WHERE LIKE %x%" tentam parametrizar wildcards e quebram. Solução: parametrize a string base, deixe wildcards fora:
# SEGURO
cursor.execute(
"SELECT * FROM users WHERE name LIKE %s",
(f"%{name}%",) # wildcards fora da query, dentro do parâmetro
)
Exemplo no repo¶
examples/sql-injection/ tem vulnerable.py e hardened.py lado a lado.
Defenses extras¶
- ORM quando possível (Django ORM, SQLAlchemy, Prisma)
- Least privilege: usuário do DB com SELECT só onde precisa
- WAF: bloqueia padrões óbvios em produção
- Logging: log queries para forense
- Pentest periódico
Como ShieldCode previne¶
A skill instrui o Claude a:
- NUNCA concatenar input em SQL
- SEMPRE usar
?/$1/%splaceholders - Aplicar
LIKEcom wildcards dentro do parâmetro - Validar tipos antes de mandar pra query
- Quando o usuário pedir "query raw", explicar o risco e ainda parametrizar