Validação de entrada e injeção
Todo valor que chega de fora (um campo de formulário, uma query string, um cabeçalho, um arquivo enviado, uma URL que você busca) é hostil até que se prove o contrário. A injeção acontece quando esse valor é tratado como código ou estrutura em vez de dado.
Checklist
- Use sempre consultas parametrizadas. Nunca monte SQL por concatenação de strings. Use parâmetros vinculados ou um ORM que faça a vinculação por você. Isso fecha a SQL injection. A mesma regra vale para NoSQL e para comandos de shell.
- Faça escape da saída de acordo com o contexto. Confie em um framework de templates ou de interface que faça escape por padrão (o React, por exemplo). Tenha muito cuidado com qualquer "renderizar HTML bruto". É assim que entra o cross-site scripting (XSS).
- Valide com allowlist, não com denylist. Defina como é um valor válido e rejeite tudo o mais, em vez de tentar bloquear entradas ruins uma a uma.
- Proteja as requisições feitas pelo servidor (SSRF). Se o servidor buscar uma URL fornecida pelo usuário, valide-a e bloqueie faixas internas e o endereço de metadados da nuvem (169.254.169.254). Use validação estrita de host e fixe o DNS para se proteger contra DNS rebinding.
- Nunca desserialize dados não confiáveis em código. Evite pickle, desserialização nativa de Java ou PHP e similares sobre bytes controlados pelo atacante. Eles executam código.
- Reforce os uploads de arquivos. Verifique o conteúdo real (magic bytes), não apenas a extensão ou o tipo declarado. Imponha um limite rígido de tamanho. Armazene os arquivos fora da raiz web, com um nome aleatório ou baseado em id, nunca com o nome enviado pelo usuário. Sirva-os com o content type correto e
X-Content-Type-Options: nosniff. Faça varredura de malware, se possível. - Valide os corpos das requisições contra um schema. Rejeite campos desconhecidos em vez de deixá-los passar (veja mass assignment em APIs e requisições).
Como testar
- Envie
' OR 1=1 --,<script>alert(1)</script>e${7*7}em todos os campos e confirme que são armazenados e exibidos como texto literal. - Aponte qualquer campo de URL para
http://169.254.169.254/e parahttp://localhost/. - Envie um arquivo HTML renomeado para
.pnge confirme que ele é rejeitado ou servido de forma inofensiva.