segurança upload arquivos

Data16/03/2026 11:42:54
Tematecnologia_dev
Subtemasegurança upload arquivos
Tipotext
Tags#security#file-upload#nginx

Resumo (IA)

Checklist de segurança para validação de upload de arquivos em Nginx/Traefik.

Conteúdo

# Security Fix: File Upload — Checklist Completo Boa captura, Daniel. O post do `ab.zerosix` está correto. Vou te dar a implementação prática de cada ponto para o teu contexto (Nginx/Traefik + PHP ou Node). --- ## ✅ As 5 Correções do Post — Como Implementar ### 1. File Content Validation (Magic Bytes) Não confiar na extensão. Ler os primeiros bytes do arquivo. **PHP:** ```php $finfo = new finfo(FILEINFO_MIME_TYPE); $mime = $finfo->file($_FILES['upload']['tmp_name']); $allowed = ['image/jpeg', 'image/png', 'image/gif', 'application/pdf']; if (!in_array($mime, $allowed)) { die('Tipo de arquivo não permitido.'); } ``` **Node.js (com `file-type`):** ```javascript import { fileTypeFromBuffer } from 'file-type'; const buffer = fs.readFileSync(filePath); const type = await fileTypeFromBuffer(buffer); const allowed = ['image/jpeg', 'image/png']; if (!type || !allowed.includes(type.mime)) { throw new Error('Arquivo inválido'); } ``` --- ### 2. MIME Type Checking (Server-side) Nunca confiar no `Content-Type` enviado pelo cliente. ```php // ERRADO - cliente pode falsificar $mime = $_FILES['file']['type']; // ❌ // CORRETO - servidor verifica $finfo = new finfo(FILEINFO_MIME_TYPE); $mime = $finfo->file($_FILES['file']['tmp_name']); // ✅ ``` --- ### 3. Random File Names ```php $ext = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION); $ext = strtolower($ext); // Whitelist de extensões $allowedExt = ['jpg', 'jpeg', 'png', 'pdf']; if (!in_array($ext, $allowedExt)) die('Extensão não permitida'); // Nome aleatório seguro $newName = bin2hex(random_bytes(16)) . '.' . $ext; // Ex: a3f8c12d...jpg ``` --- ### 4. Disable Script Execution na pasta uploads/ **Nginx** (bloquear PHP dentro da pasta de uploads): ```nginx location ~* /uploads/.*\.(php|php5|phtml|sh|cgi|pl)$ { deny all; return 403; } ``` **Apache (.htaccess dentro de /uploads/):** ```apache <FilesMatch "\.(php|php5|phtml|sh|cgi|pl)$"> Deny from all </FilesMatch> Options -ExecCGI AddHandler cgi-script .php .php5 .phtml .sh ``` --- ### 5. Store Outside Web Root ```php // ERRADO - acessível por URL direta $uploadDir = '/var/www/html/uploads/'; // ❌ // CORRETO - fora do web root $uploadDir = '/var/www/storage/uploads/'; // ✅ // Servir via script controlado: ``` **Script para servir arquivo com controle:** ```php // download.php?file=abc123.jpg $filename = basename($_GET['file']); $path = '/var/www/storage/uploads/' . $filename; // Validações antes de servir if (!file_exists($path)) die('404'); $mime = mime_content_type($path); header('Content-Type: ' . $mime); readfile($path); ``` --- ## 🔒 Bônus: Checklist Extra para Teu Stack ```bash # Verificar se pasta de uploads tem permissão de execução ls -la /var/www/html/uploads/ # Remover permissão de execução chmod -x /var/www/html/uploads/ chmod 644 /var/www/html/uploads/* # No Docker: montar uploads como volume separado # e garantir que o container web não tenha acesso de exec ``` ### Traefik — Header de Segurança: ```yaml # No seu middlewares do Traefik headers: customResponseHeaders: X-Content-Type-Options: "nosniff" # Impede MIME sniffing X-Frame-Options: "SAMEORIGIN" Content-Security-Policy: "default-src 'self'" ``` --- ## 📋 Resumo Rápido | Proteção | O que previne | |---|---| | Magic Bytes | Arquivo `.jpg` com código PHP dentro | | MIME server-side | Cliente forjando Content-Type | | Nome aleatório | Path traversal + execução direta | | Sem exec em /uploads | Webshell mesmo que o upload passe | | Fora do web root | Acesso direto por URL ao arquivo | --- Quer que eu faça um **script de auditoria** que roda no teu servidor e verifica automaticamente todas essas brechas no teu ambiente atual?

Metadata

msg_idA51120DFAD11EF4EC2E11C80D86F1390
JID29322177998957@lid
fromMeTrue
Classificado02/05 14:00
AppFlowy✅ sincronizado