Where
-Infinity
0
Severity
8.7
Malicious File Upload
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/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

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.

1 / 2
Source: NVD
First published (updated )
Severity
5.3
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Cross-user wishlist item import via shared wishlist code, leading to private option disclosure and file-disclosure variant

Summary

The shared wishlist add-to-cart endpoint authorizes access with a public sharingcode, but loads the acted-on wishlist item by a separate global wishlistitemid and never verifies that the item belongs to the shared wishlist referenced by that code.

This lets an attacker use:

- a valid shared wishlist code for wishlist A - a wishlist item ID belonging to victim wishlist B

to import victim item B into the attacker's cart through the shared wishlist flow for wishlist A.

Because the victim item's stored buyRequest is reused during cart import, the victim's private custom-option data is copied into the attacker's quote. If the product uses a file custom option, this can be elevated to cross-user file disclosure because the imported file metadata is preserved and the download endpoint is not ownership-bound.

Vulnerability Type

- Broken object-level authorization / IDOR - Cross-user data disclosure - Cross-user file disclosure variant

Root Cause

In app/code/core/Mage/Wishlist/controllers/SharedController.php, the shared flow does:

php $item = Mage::getModel('wishlist/item')->load($itemId); $wishlist = Mage::getModel('wishlist/wishlist')->loadByCode($code); ... $item->addToCart($cart);

Relevant lines:

- SharedController.php:86 loads the wishlist item by global ID - SharedController.php:87 loads the wishlist by shared code - SharedController.php:99 imports the item into cart

There is no check that:

php $item->getWishlistId() == $wishlist->getId()

The safe owner flow in app/code/core/Mage/Wishlist/controllers/IndexController.php:521-528 does preserve this binding by deriving the wishlist from item->getWishlistId().

The imported item keeps its original buyRequest because app/code/core/Mage/Wishlist/Model/Item.php:370-372 passes that stored request directly into:

php $cart->addProduct($product, $buyRequest);

Security Impact

Baseline impact

An attacker can import another user's private wishlist item into the attacker's own cart, using an unrelated shared wishlist code.

This is a clear cross-user authorization bypass. The victim item's private configuration is copied into the attacker's quote, including custom-option values such as personalized text.

Stronger variant: cross-user file disclosure

If the victim item contains a custom option of type file, the imported quote item preserves file metadata such as:

- quotepath - orderpath - secretkey

The file option renderer in app/code/core/Mage/Catalog/Model/Product/Option/Type/File.php:547-552 generates a download URL from:

- the imported sales/quoteitemoption ID - the preserved secretkey

The downloader in app/code/core/Mage/Sales/controllers/DownloadController.php:150-185:

- loads quote item option by global ID - verifies only product option type and secretkey - reads the file from orderpath or quotepath

It does not verify ownership of the quote item, order, or original wishlist item. This creates a cross-user file disclosure path once victim file metadata has been imported.

Steps To Reproduce

Lab data

- shared wishlist A: - wishlistid = 1 - customerid = 2 - sharingcode = 6376bb8c37a09c2de3664bd8cdc16412 - victim wishlist B: - wishlistid = 2 - customerid = 3 - victim item: - wishlistitemid = 1 - wishlistid = 2 - productid = 2 - victim private text option marker: - VICTIM-MARKER-49040822

Reproduction

Send:

http GET /wishlist/shared/cart/?code=6376bb8c37a09c2de3664bd8cdc16412&item=1

Where:

- code belongs to shared wishlist A - item=1 belongs to victim wishlist B

Expected result

The request should be rejected because the item does not belong to the shared wishlist referenced by the sharingcode.

Actual result

The application imports victim item 1 into the attacker's quote anyway.

Verified Evidence

Baseline variant

Previously verified at quote/option level in lab:

text option1 = VICTIM-MARKER-49040822

This shows that the attacker's cart received victim-private custom-option data from another user's wishlist item.

File-disclosure variant

Previously verified in lab after importing a victim file-option payload:

text /sales/download/downloadCustomOption/id/9/key/86fca9b61c0b891b52fb/

This URL was generated from imported quote item option data containing the victim file metadata and secret key.

Why This Is A Valid Bug

This is not a timing issue and does not depend on non-default security settings.

The bug is a direct authorization failure:

- authorization is based on wishlist A's share code - the acted-on object is item B from another wishlist - there is no item-to-wishlist binding check - victim-controlled item state is then copied into attacker-controlled cart state

That is a broken object-level authorization issue with clear cross-user impact.

Remediation

In SharedController::cartAction(), reject any request where the loaded item does not belong to the wishlist loaded from the share code:

php $item = Mage::getModel('wishlist/item')->load($itemId); $wishlist = Mage::getModel('wishlist/wishlist')->loadByCode($code);

if (!$item->getId() || !$wishlist->getId() || (int) $item->getWishlistId() !== (int) $wishlist->getId()) { return $this->forward('noRoute'); }

Defense in depth:

- bind sales/download/downloadCustomOption to the current quote/order owner instead of trusting only id + secretkey

1 / 2
Source: GitHub
First published (updated )
Severity
4.9
Path Traversal
AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:N/A:N

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 Dataflow module in OpenMage LTS uses a weak blacklist filter (strreplace('../', '', $input)) to prevent path traversal attacks. This filter can be bypassed using patterns like ..././ or ....//, which after the replacement still result in ../. An authenticated administrator can exploit this to read arbitrary files from the server filesystem. Version 20.17.0 patches the issue.

1 / 2
Source: MITRE
First published (updated )
Severity
8.1
AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H

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, PHP functions such as getimagesize(), fileexists(), and isreadable() 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. Version 20.17.0 patches the issue.

1 / 2
Source: MITRE
First published (updated )
Severity
5.3
EPSS
0.03%
Infoleak
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N

Impact

The admin url can be discovered without prior knowledge of its location by exploiting the X-Original-Url header on some configurations.

Patches

The bug comes from the Zend library.

Workarounds

Unset the X-Original-Url header in the web server configuration.

Resources

https://hackerone.com/bugs?subject=openmage&reportid=3416312

Upon deeper investigation, it was initially not found, but then it was realized that the search excluded the vendor/ directory. This is coming from the ZendController module. Here is another tip from 2016 - it is surprising that this was not somehow patched already!

https://peterocallaghan.co.uk/2016/12/magento-poisoning-cache/ (dead link now..)

Credit

Anees Hyder (anees0xdev) on HackerOne https://hackerone.com/anees0xdev/hacktivity?type=user

1 / 2
Source: GitHub
First published (updated )
Severity
4.8
XSS
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Summary OpenMage versions v20.15.0 and earlier are affected by a stored Cross-Site Scripting (XSS) vulnerability that could be abused by an admin with direct database access or the admin notification feed source to inject malicious scripts into vulnerable fields. Malicious JavaScript may be executed in a victim’s browser when they browse to the page containing the vulnerable field.

Details Unescaped translation strings and URLs are printed into contexts inside app/code/core/Mage/Adminhtml/Block/Notification/Grid/Renderer/Actions.php. A malicious translation or polluted data can inject script. - Link labels use () without escaping. - ’deleteConfirm()’ embeds a message without escaping.

PoC 1. Add XSS to admin locale (e.g. app/locale/enUS/local.csv): "Read Details","<img src=x onerror=alert(123)>" "Mark as Read","<script>alert(123)</script>" 2. Flush Cache. Make sure locale is set to enUS. 3. Add any admin notification (e.g. via test.php) <?php require 'app/Mage.php'; Mage::app('admin'); Mage::getModel('adminnotification/inbox')->setData([ 'severity' => MageAdminNotificationModelInbox::SEVERITYNOTICE, 'dateadded' => now(), 'title' => 'XSS renderer test', 'description' => 'Testing actions renderer', 'url' => 'https://example.com', // makes the "Read Details" link appear 'isread' => 0, // makes the "Mark as Read" link appear 'isremove' => 0, ])->save(); 4. Open Admin → System → Notifications → Inbox. 5. Profit.

Impact The vulnerability is only exploitable by an attacker with administrative or translation privileges. Malicious JavaScript may be executed in a victim’s browser when they browse to the admin page containing the vulnerable fields.

1 / 2
Source: GitHub
First published (updated )
Severity
7.2
Input Validation
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H

OpenMage magento-lts is an alternative to the Magento CE official releases. Due to missing sanitation in data flow in versions prior to 19.4.15 and 20.0.13, it was possible for admin users to upload arbitrary executable files to the server. OpenMage versions 19.4.15 and 20.0.13 have a patch for this Issue.

First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203