Explorando Vulnerabilidades de Upload de Arquivos sem Quebrar a Lei
Como bypassar validacoes de upload em lab proprio, mapear classes de falhas e endurecer webservers contra RCE via arquivo malicioso.
Um endpoint de upload mal configurado continua sendo uma das formas mais baratas de transformar um simples formulario em RCE. Em um lab montado com DVWA, OWASP Juice Shop e um Nginx 1.25 reverso, conseguimos em menos de 40 minutos passar de 'upload de avatar' para shell como www-data. Antes de mostrar qualquer payload, vale lembrar o contrato: o alvo e a propria VM, isolada em uma rede 10.10.0.0/24 sem rota para a internet, e o objetivo final e escrever regras de hardening, nao colecionar troféus. Se voce ainda nao tem esse ambiente de pé, recomendo seguir Pentest Web do Zero: Montando um Lab Seguro com DVWA, Juice Shop e Burp Suite antes de continuar.
A primeira classe de falha que aparece e a validacao por extensao no lado do cliente. Em PHP legado, e comum ver uma lista negra (.php, .phtml, .php5) e nenhuma checagem de Content-Type real. Renomear shell.php para shell.pHp.jpg, interceptar com Burp e devolver com Content-Type image/jpeg derruba 80% dos filtros amadores que vejo em CTFs corporativos. Em um teste recente contra um modulo de curriculo, bastou anexar GIF89a; em um arquivo .gif renomeado para .phtml para obter execucao. O que falhou nao foi 'o regex', foi a arquitetura: o Apache estava configurado com AddHandler para qualquer coisa que terminasse em .phtml em qualquer pasta.
A segunda camada interessante e o parsing duplo do Nginx antigo (CVE-2013-4547 e variantes modernas). Um arquivo chamado shell.jpg\x00.php ainda engana stacks que combinam Nginx + PHP-FPM com pathinfo mal configurado. No lab, reproduzi o cenario com nginx:1.14-alpine e php:7.2-fpm so para ter uma referencia historica; com Nginx 1.25 e cgi.fix_pathinfo=0, o mesmo payload morre. Esse tipo de exercicio se conecta bem com o que discuto em SQL Injection na Pratica: Explorando, Detectando e Mitigando em Lab Controlado: nao adianta caçar uma vulnerabilidade especifica se voce nao entende a cadeia inteira de processamento da requisicao, do load balancer ao interpretador.
Quando o backend valida magic bytes, o jogo muda. Polyglots GIF/PHP funcionam contra getimagesize(), mas falham contra finfo + Imagick com reprocessamento. O truque ai e atacar o pipeline de transformacao: ImageMagick com policies frouxas ainda processa MVG e SVG, e a familia de bugs ImageTragick continua aparecendo em fork de plataformas LMS. Em um cliente fintech, encontrei um upload de comprovante que rodava convert sem -limit memory e sem policy.xml restrito; um SVG de 12KB com xlink:href apontando para file:///etc/passwd vazou conteudo no PDF gerado. Para quem quer entender o lado web puro de SSRF derivado disso, SSRF Descomplicado: Explorando Cloud Metadata em Lab AWS Local cobre o caso AWS quase identico.
Outra superficie subestimada e onde o arquivo vai parar. Storage em /var/www/uploads servido diretamente pelo Apache e o classico, mas vejo o mesmo problema em buckets S3 com Content-Disposition errado e em CDNs que reprocessam HTML. Path traversal no nome do arquivo (../../tmp/cron.d/pwn) ainda funciona contra middlewares Node que confiam no originalname do Multer. Para um checklist mais formal de teste, especialmente em APIs JSON com base64 embutido, vale cruzar com Pentest de APIs REST e GraphQL: Checklist Tecnico para Bug Bounty Legal e validar limites de tamanho, mimetype declarado vs detectado, e quotas por usuario autenticado.
Do lado defensivo, as regras que pago para escrever em relatorio sao chatas e funcionam: gerar nome aleatorio (UUIDv7), armazenar fora do document root, servir via handler que forca Content-Disposition: attachment e Content-Type: application/octet-stream, validar mimetype com libmagic no servidor, e bloquear extensoes duplas no proprio Nginx com location ~* \.(php|phtml|phar)\. { deny all; }. Em containers, monto o volume de upload como noexec,nosuid e rodo um clamav em sidecar. Auditoria continua entra em AppSec Shift-Left: SAST, SCA e Secrets Scanning sem Travar o Time, onde Semgrep pega regex de validacao fraca antes do deploy.
Um detalhe etico que repito em treinamento: replicar essas tecnicas contra um SaaS de producao 'so para testar' nao e bug bounty, e crime no Brasil sob a Lei 12.737 e o Marco Civil. Programas legitimos publicam escopo explicito, e mesmo dentro deles, exfiltrar /etc/passwd e desnecessario quando um id da VM ja prova a falha. A diferenca entre pesquisador e reu costuma ser o snapshot da VM e o termo de autorizacao. Takeaway pratico: na proxima sprint, pegue um endpoint de upload do seu produto, escreva um teste integrado que tenta subir shell.phtml, .htaccess, polyglot GIF/PHP e SVG com xlink, e falhe o pipeline se qualquer um for aceito. Isso vale mais que cem horas de leitura.