On January 9th, we released Commerce 0.10.3 which includes a fix for an information disclosure vulnerability. Our limited early announcement did not include specific information about the vulnerability, to protect existing users from being exploited before they had a chance to upgrade. In this full disclosure we want to share with you more details of what happened.
Vulnerability
In the checkout, Commerce needs to keep track of the current order information. It uses two methods for this: some data is kept in the session (managed by MODX), and as soon as a customer goes from the cart into the checkout, the order is saved to the database and the current order ID is stored in a cookie.
As long as the customer is in the checkout, those two things will be checked to determine the current order, so additional data (customer address and shipping/payment methods) can be retrieved from the database and updated. The session data takes precedence over the cookie value, but both are trusted.
The problem is the trust Commerce placed in the cookie value. It is trivial to set cookie values, and by simultaneously unsetting the MODX session cookie (so Commerce has no session data to look at) and setting an arbitrary number in the Commerce order cookie, it was possible to trick Commerce into loading someone else’s order. This exploit was only possible for concept orders (orders that hadn’t been completed), which can be seen in the Commerce dashboard under Orders > Concept. Some of those orders may have contained customer address information.
As we used an auto-incrementing value in the cookie (the ID of the actual order object), it was easy to loop over order IDs to extract potential information.
Based on our analysis, we determined a CVSS score of approximately 8.2 for this vulnerability, which is high risk.
Resolution
Commerce 0.10.3 fixes this vulnerability. No other protection mechanisms are available.
While we have not disabled the cookie, the cookie now contains an impossible to predict 64 character random secret instead of the auto incrementing integer. This secret is generated by PHP7’s random_bytes function, providing a cryptographically secure random, with the random_compat library being used as fallback before PHP7.
This stops brute forcing/enumerating potential order secrets. While we still put trust in the cookie, the session cookie is only 32 characters in length and can have much more serious security impact when compromised, so we consider a 64 character secret more than safe enough.
Timeline
January 3rd, 2018: initial discovery by the modmore team during regular development
January 3rd, 2018: initial fix targeting v0.11 release branch ready for testing
January 8th, 2018: fix backported to v0.10 release branch to allow a faster release
January 9th, 2018: fix released in v0.10.3 and announcement (https://www.modmore.com/blog/2018/commerce-0.10.3/) published
January 9th, 2018: email blast sent to customers with Commerce installations
February 12th, 2018: disclosure published