**Note: The content in this article is only for educational purposes and understanding of cybersecurity concepts. It should enable people and organizations to have a better grip on threats and know how to protect themselves against them. Please use this information responsibly.**
File upload functionalities are commonly found in modern web applications, allowing users to upload avatars, documents, or other resources. However, if not properly secured, these upload mechanisms can be exploited by attackers to upload malicious files — particularly server-side scripts like PHP — that can then be executed on the server. This leads to serious consequences, including remote code execution (RCE), data leakage, and complete server takeover.
A. Remote code execution via web shell upload
Lab: Remote code execution via web shell upload | Web Security Academy
In this lab, we’re presented with an image upload feature that does not perform any validation or sanitization on uploaded files. This creates a critical security flaw — the server allows arbitrary files, including executable PHP scripts, to be uploaded and stored in a web-accessible directory. This misconfiguration can be exploited by uploading a web shell that reads sensitive server files. Our objective is to exploit this vulnerability by uploading a PHP script that will read the contents of /home/carlos/secret, retrieve the secret, and submit it to solve the lab.
Step 1: Click on “My account”. Use the credentials provided:
Username: wiener
Password: peter

Step 2: You’ll see an option to upload an avatar image. Upload any valid image file.

Step 3: Click on upload. Now click on the Back to My Account link to see the uploaded photo.

The photo has been uploaded.

Step 4: Go to Proxy → HTTP history. Use the Filter bar → Filter by MIME Type → Enable Images to narrow down image requests.

Step 5: Find 2 requests:
- POST upload request to upload the image to the server.

- GET request made by the server to retrieve the uploaded image.

Send both these requests to the repeater by right-clicking on these requests and click on Send to Repeater.
Step 6: In the upload request in the repeater, create a filename called exploit.php. Add this PHP script.
<?php echo file_get_contents(‘/etc/passwd’); ?>
Click on Send to upload the exploit.php.

The site doesn’t validate the file type, so it accepts and saves the PHP file.
Alternative
<?php system($_GET[‘cmd’]); ?>

Step 7: Go to retrieve image request in repeater, send a request to fetch exploit.php.

The server will execute your PHP file because the /files/avatars/ directory is misconfigured to execute PHP.
Alternative
Go for this: /exploit.php?cmd=cat+/etc/passwd

Step 8: To solve the lab, go to upload request and upload this code
<?php echo file_get_contents(‘/home/carlos/secret’); ?>

Step 9: Go to the retrieve image request and send it. This PHP script will read Carlos’s secret file and print its contents. Paste the secret into the input field to solve the lab.

Through this lab, we successfully exploited a file upload vulnerability that led to remote code execution. By uploading a malicious PHP script through the avatar feature and accessing it via its predictable file path, we were able to retrieve and expose sensitive data stored on the server.
Conclusion
To prevent such critical vulnerabilities, developers and security teams should implement multiple layers of defense on file upload functions, including:
- Strict file type whitelisting (e.g., allow only .jpg, .png).
- MIME type validation on both client and server sides.
- Content inspection (checking magic bytes or signatures of uploaded files).
- Renaming uploaded files to prevent execution (e.g., using randomized names with safe extensions).
- Storing uploads outside the web root, or using separate storage servers or buckets.
- Disabling script execution in upload directories through server configuration (e.g., .htaccess or nginx config).
- Setting appropriate permissions on uploaded files.