Pentest

Exploring File Upload Vulnerabilities Without Breaking the Law

Por Equipe Basilisk ·

How to bypass upload validations in your own lab, map the bug classes, and harden webservers against RCE via malicious file.

A misconfigured upload endpoint is still one of the cheapest ways to turn a humble form into RCE. In a lab built with DVWA, OWASP Juice Shop and an Nginx 1.25 reverse proxy, we went from 'avatar upload' to a www-data shell in under 40 minutes. Before any payload, the contract matters: the target is our own VM, isolated on a 10.10.0.0/24 network with no internet route, and the goal is writing hardening rules, not collecting trophies. If you do not have that environment stood up yet, walk through Web Pentesting From Scratch: Building a Safe Lab with DVWA, Juice Shop and Burp Suite before continuing.

The first bug class that shows up is client side extension validation. Legacy PHP commonly ships a blacklist (.php, .phtml, .php5) with zero real Content-Type check. Renaming shell.php to shell.pHp.jpg, intercepting with Burp and forcing Content-Type image/jpeg defeats around 80% of the amateur filters I see in corporate CTFs. In a recent test against a resume module, a 12 byte GIF89a; stored in a .gif renamed to .phtml gave full execution. What failed was not the regex; it was the architecture: Apache had AddHandler bound to anything ending in .phtml in any folder.

The second interesting layer is old Nginx double parsing (CVE-2013-4547 and its modern descendants). A file named shell.jpg\x00.php still tricks stacks combining Nginx + PHP-FPM with sloppy pathinfo. In the lab I rebuilt the scenario with nginx:1.14-alpine and php:7.2-fpm just for historical reference; with Nginx 1.25 and cgi.fix_pathinfo=0 the same payload dies. This kind of drill pairs well with SQL Injection in Practice: Exploiting, Detecting and Mitigating in a Controlled Lab: chasing a single CVE is pointless if you do not understand the full request pipeline from load balancer to interpreter.

When the backend validates magic bytes, the game changes. GIF/PHP polyglots beat getimagesize() but fail against finfo plus Imagick with reprocessing. The trick is to attack the transformation pipeline: ImageMagick with loose policies still parses MVG and SVG, and the ImageTragick family keeps surfacing in LMS forks. At a fintech client I found a receipt upload calling convert without -limit memory and with an empty policy.xml; a 12KB SVG with xlink:href pointing at file:///etc/passwd leaked content into the generated PDF. For the pure web side of SSRF derived from this, SSRF Demystified: Exploiting Cloud Metadata in a Local AWS Lab covers the nearly identical AWS case.

Another underrated surface is where the file ends up. Storage at /var/www/uploads served directly by Apache is the classic, but I see the same problem in S3 buckets with the wrong Content-Disposition and in CDNs that reprocess HTML. Path traversal inside the filename (../../tmp/cron.d/pwn) still works against Node middleware that trusts Multer originalname. For a more formal test checklist, especially on JSON APIs with embedded base64, cross check with REST and GraphQL API Pentest: Technical Checklist for Legal Bug Bounty and validate size limits, declared vs detected mimetype, and per-user authenticated quotas.

On the defensive side, the rules I get paid to write in reports are boring and they work: random filename (UUIDv7), store outside the document root, serve through a handler that forces Content-Disposition: attachment and Content-Type: application/octet-stream, validate mimetype with libmagic server side, and block double extensions in Nginx itself with location ~* \.(php|phtml|phar)\. { deny all; }. In containers I mount the upload volume as noexec,nosuid and run clamav as a sidecar. Continuous auditing belongs in AppSec Shift-Left: SAST, SCA and Secrets Scanning Without Slowing the Team, where Semgrep catches weak validation regex before deploy.

An ethical point I repeat in training: replicating these techniques against a production SaaS 'just to check' is not bug bounty, it is a felony under most computer misuse statutes. Legitimate programs publish explicit scope, and even inside them, exfiltrating /etc/passwd is unnecessary when the VM id already proves the bug. The difference between researcher and defendant is usually the VM snapshot and the written authorization. Practical takeaway: next sprint, pick one upload endpoint from your product, write an integration test that tries shell.phtml, .htaccess, a GIF/PHP polyglot and an SVG with xlink, and fail the pipeline if any of them is accepted. That is worth more than a hundred hours of reading.

Nenhum comentário ainda

Seja o primeiro a comentar.

Deixe seu comentário

Entre com sua conta Canverly para comentar. Você pode usar a mesma conta em qualquer site da rede.

Entrar com Canverly