Validación de entrada e inyección
Todo valor que llega desde fuera (un campo de formulario, una cadena de consulta, un encabezado, un archivo subido, una URL que obtienes) es hostil hasta que se demuestre lo contrario. La inyección ocurre cuando ese valor se trata como código o estructura en lugar de como datos.
Lista de verificación
- Usa siempre consultas parametrizadas. Nunca construyas SQL concatenando cadenas. Usa parámetros vinculados o un ORM que los vincule por ti. Esto cierra la inyección SQL. La misma regla se aplica a NoSQL y a los comandos de shell.
- Escapa la salida según el contexto. Apóyate en un framework de plantillas o de interfaz que escape por defecto (React, por ejemplo). Ten mucho cuidado con cualquier mecanismo de "renderizar HTML sin procesar". Por ahí es como entra el cross-site scripting (XSS).
- Valida contra una lista de permitidos, no contra una lista de bloqueados. Define cómo es un valor válido y rechaza todo lo demás, en lugar de intentar bloquear entradas maliciosas.
- Protege las solicitudes del lado del servidor (SSRF). Si el servidor obtiene una URL proporcionada por el usuario, valídala y bloquea los rangos internos y la dirección de metadatos de la nube (169.254.169.254). Usa una validación estricta del host y fija el DNS para contrarrestar el DNS rebinding.
- Nunca deserialices datos no confiables en código. Evita pickle, la deserialización nativa de Java o PHP y similares sobre bytes controlados por un atacante. Ejecutan código.
- Refuerza las subidas de archivos. Verifica el contenido real (magic bytes), no solo la extensión o el tipo declarado. Aplica un límite de tamaño estricto. Guarda los archivos fuera de la raíz web, con un nombre aleatorio o basado en id, nunca con el nombre que dio el usuario. Sírvelos con el tipo de contenido correcto y
X-Content-Type-Options: nosniff. Analiza en busca de malware si puedes. - Valida los cuerpos de solicitud contra un esquema. Rechaza los campos desconocidos en lugar de dejarlos pasar (consulta la asignación masiva en APIs y solicitudes).
Cómo probar
- Envía
' OR 1=1 --,<script>alert(1)</script>y${7*7}en cada campo y confirma que se almacenan y se muestran como texto literal. - Apunta cualquier entrada de URL a
http://169.254.169.254/y ahttp://localhost/. - Sube un archivo HTML renombrado a
.pngy confirma que se rechaza o se sirve inerte.