File Upload Vulnerability in ZYXEL Configuration Migration Tool
"Hackers don’t knock before entering; they exploit every open window."
Summary
A few years ago, I needed to migrate the configuration of an old Zyxel USG40
firewall to an ATP100
.
To my surprise, I discovered that Zyxel offers a cloud-based tool to automatically perform this migration: you simply upload the existing configuration file and download the converted version.
Needless to say, as soon as I saw that beautiful upload form, I couldn’t help but start thinking: "How can I craft a payload to gain backend access?"
First Analysis
The first step was to upload a configuration file and inspect the behavior of the web page after clicking the "Load" button. A POST request is fired to the following endpoint:
File Upload Vulnerability in ZYXEL Configuration Migration Toolhttps://convert.cloud.zyxel.com/converter-5.0.1/common/receivefile.php
By intercepting the request with Burp Suite, we can clearly see the data being sent to receivefile.php
:
- The source filename
- The file content
- The target filename
Initial Test
My first idea was simple: attempt to upload a .conf
file, but disguise it as a .php
script.
So I renamed the file to hizyxel.php
, replaced its content with PHP code that simply echoes a string, and set uploadedfile
to hizyxel.php
.
Submitting the modified request returned no error, which suggested the upload had been accepted.
The next step was to proceed with the conversion by clicking the "Convert" button. Again, Burp Suite intercepted the request and revealed a JSON payload specifying the filename and a random seed:
However, I noticed that the converter script ignored the filename previously passed and instead generated a new name with the seed appended.
When I initially tried accessing the file from the browser, it failed because I had forgotten that the script adds a suffix (e.g., -17839) to the filename during processing. Once I corrected the filename by including the seed, I was finally able to reach my PHP file.
Webshell
This time, I uploaded a new configuration file, replacing its content with a simple web shell.
Once again, no error message appeared. I repeated the conversion process, manipulating the payload to preserve the malicious content.
Then, by navigating to the rainpwn file and appending the ?command= parameter, I was able to execute commands on the server:
Conclusion
What began as a legitimate migration task turned into a demonstration of how even a seemingly harmless configuration upload feature can be weaponized if file validation and input sanitization are improperly implemented.
The lesson is simple:
Every upload field is a potential attack vector. If you don't control it, someone else will.
After responsibly disclosing the vulnerability to Zyxel, the issue was promptly fixed. As recognition for my contribution to improving their security posture, Zyxel issued an official certificate of appreciation.
Disclosure Timeline
- 2022-08-12 — Vulnerability reported to Zyxel via <security@zyxel.com.tw>.
- 2022-08-15 — Zyxel acknowledged receipt of the report.
- 2022-08-25 — Zyxel confirmed the vulnerability and stated it would be fixed before mid-September.
- 2022-09-12 — After applying the patch, I discovered it was still possible to delete arbitrary files on the system by abusing the
cgi-bin/removefiles.py
endpoint. A follow-up report was sent. - 2022-09-16 — Zyxel responded, confirming a new fix would be released in October or earlier.
- 2022-09-23 — Zyxel released a patch for the Configuration Migration Tool, addressing the reported issues.