Magento, which was acquired by Ebay Inc back in 2011, is one of the most popular e-commerce platforms written in PHP. There is an interesting bug bounty program in place that offers bounties of up to 10,000$ for Information Disclosure and Remote Code Execution vulnerabilities. In November 2014, I decided to give it a try, so I started looking for security bugs in Magento CE, and almost immediately I discovered a PHP Object Injection vulnerability which (un)fortunately requires administrator privileges in order to be exploited. I thought this reason was good enough to choose not to report my finding under their bug bounty program, since Magento administrators should already be able to upload and execute arbitrary code through the administration panel. However, after a couple of weeks a friend of mine encouraged me to submit the finding, because you never know. So I did it, and when I finished writing my report including a PoC, and I was about to send it, I noticed that the bug had already been (silently!) patched only a few days earlier! The researcher who reported the vulnerability has been awarded with 2,500$ for the very same finding…
A couple of months later, in February 2015, there was a lot of rumors about what I consider a very nice piece of research which chains several vulnerabilities in Magento that ultimately allow an unauthenticated attacker to execute arbitrary PHP code on the web server. Getting inspired by these vulnerabilities, I decided to come back to Magento source code looking for new security bugs, and I discovered and reported two vulnerabilities which made me win two bounties I’d never thought I’d receive: 8,000$ and9,000$. Both of the vulnerabilities were discovered in February 2015, however I decided to report only a “potential Remote Code Execution” at a first stage, because I thought the other one – a trivial information leakage bug – had a security impact too low in order to be eligible for the bug bounty program, in other words I thought it wasn’t a “real” security issue. I was wrong (again!)…
There is a class of vulnerabilities that might affect certain PHP applications which uses an “exploitable” autoloading mechanism. The “Autoloading Classes” feature has been introduced in PHP 5.0 with the magic function __autoload() which is automatically called when your code references a class or interface that hasn’t been loaded yet. So, instead of including every needed class by hand, it is possible to register a function that gets called as soon as the code tries to instantiate an unknown class. This function gets passed the unknown class name and is responsible for including the right file that contains the class definition. While this feature is extremely useful and powerful, it might introduce potential Local/Remote File Inclusion vulnerabilities when user-controlled input is used as a class name. Indeed, if an attacker can control the class name variable passed to an autoloading function, she could try to play around with it in order to include an arbitrary file and execute PHP code remotely. There are multiple ways to trigger the autoloader, the most obvious is class instantiation using the new operator. In addition to that, there are some PHP functions which can be considered a sensitive sink for this class of vulnerabilities. Here is an incomplete list:
So, when user-controlled input (tainted data) enters one of these sensitive sinks there’s a chance for the application to be vulnerable to an “Autoloaded File Inclusion” attack. Let’s see a simple example of vulnerable code:
In this example an attacker controls a class name via the GET parameter “class”, which is first used with the class_exists()function (triggering the autoloader in case it is an unknown class) and then to instantiate a new object. This means that the attacker can control the $class_name variable passed to the autoloader, therefore it could be possible to include arbitrary files from both local or remote resources by invoking URLs like these:
In the first case the autoloader will try to include and execute the PHP code located at http://attacker.com/shell.php, resulting in a Remote File Inclusion (RFI); while in the second case the autoloader will try to include and execute the PHP code located into the file /tmp/cache/attacker_controlled/file.php, resulting in a Local File Inclusion (LFI). Furthermore, in cases like this where the attacker controls the classname’s prefix, in addition to http:// other PHP wrappers might be abused in order to execute arbitrary PHP code.
According to the official PHP documentation “a valid class name starts with a letter or underscore, followed by any number of letters, numbers, or underscores”. That means an attacker cannot include arbitrary files via class names because it should not be possible to e.g. use path traversal sequences (../../) through them. But here comes the problem: there was a bug in the PHP core which allowed to invoke class autoloaders with invalid class names. This bug was solved in January 2014 with the release of PHP versions 5.4.24 and 5.5.8, and that’s probably one of the reasons why Magento’s security engineers have undervalued this issue.
The vulnerability in Magento is caused by the code that handles the “catalogProductCreate” SOAP API call. The vulnerable code is located into the /app/code/core/Mage/Catalog/Model/Product/Api/V2.php script:
This method expects the $productData parameter to be an array (in form of a stdClass object) and uses the property_exists()function with it. However, an attacker can manipulate a SOAP request arbitrarily and send the $productData parameter in form of a string. In this case, if the string passed to the property_exists() function is an unknown class, any registered autoloader function will be triggered. When the property_exists() function is called there’s only one autoloader function registered, that is theVarien_Autoload::autoload() method:
In such a scenario, the $class parameter automatically passed to this method is exactly the same string value sent through the$productData parameter from the SOAP request, which after some replacementes and a “.php” string appended to it, is being used in a call to the include() function. This may result in an arbitrary file inclusion (both from local or remote resources) and could be exploited to include and execute arbitrary PHP code. There are some conditions which should be met to exploit this vulnerability:
- an API user account with privileges to create a catalog product is required;
- in order to include arbitrary files from remote locations, Magento should run on PHP before 5.4.24 or 5.5.8, because such versions have fixed the issue related to invalid class names in the autoloading process;
- in order to include arbitrary files from remote locations the “allow_url_include” directive must be set to On;
- in case the “allow_url_include” directive is set to Off it might still be possible to include files from remote locations using thessh2.sftp:// wrapper (which requires the SSH2 extension to be installed) or execute arbitrary OS commands leveraging theexpect:// wrapper (which requires the Expect extension to be installed).
NOTE: if Magento is running on PHP version after 5.4.23 or 5.5.7 the vulnerability could still be exploited by including a local file with a .php extension (something like /tmp/test.php). If Magento is running on PHP before 5.3.4 the vulnerability could be exploited to include arbitrary local files with any extension (e.g. a session file containing malicious PHP code injected by the attacker) because NULL bytes are allowed within the path (see CVE-2006-7243).
Proof of Concept
A remote attacker with valid API credentials could send a SOAP request like the following in order to exploit the vulnerability:
POST /magento/index.php/api/v2_soap HTTP/1.0
<?xml version=”1.0″ encoding=”UTF-8″?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV=”http://schemas.xmlsoap.org/soap/envelope/” xmlns:ns1=”urn:Magento” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:SOAP-ENC=”http://schemas.xmlsoap.org/soap/encoding/” SOAP-ENV:encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/”>
The “productData” parameter has been encoded in base64 within the SOAP request, and the decoded string is the following:
This means that leveraging the ftp:// wrapper, an attacker might be able to force Magento to load and execute malicious code from a FTP server under its control. In this example, the attacker only has to put the malicious code under /home/attacker/evil.php. However, as we said before, other PHP wrappers might be abused, potentially leading to direct arbitrary PHP code execution.
Responsible Disclosure Timeline
As I was saying, I reported this vulnerability in late February 2015, and I received the first reply from the Magento Security Team on June 22, 2015, stating that my submission was not eligible for the bug bounty program, because it was found to be invalid and not actionable. The reason for the rejection was that there are too many requirements to exploit the vulnerability. First of all, it requires Magento to be running on outdated PHP versions, because this kind of vulnerability has been fixed in the PHP core engine at the beginning of 2014. However, until today there are still many websites out there using such outdated PHP versions. That should be one of the reasons why the Magento Security Team replied on June 24, stating the following:
We were able to confirm your issue. Even though it requires knowing API credentials, it should not be possible to execute such actions. The PHP versions that are additionally vulnerable, while old are still used in popular distributions like RHEL 7.1. We will schedule fixing this issue for our next product release given lower priority. We will inform you regarding possible awards associated with this report.
On August 4, 2015, a bundle of patches (SUPEE-6482), which resolved several security-related issues, including the one I reported in February, was released by the Magento team. On the same day Magento released new versions (Community Edition 184.108.40.206 and Enterprise Edition 220.127.116.11) that include SUPEE-6482 along with other security patches. On August 13 I sent them an email asking whether there was any chance to get a bounty for reporting such a vulnerability. I had to ping them twice more, before getting their reply on August 25:
Hello Egidio, Congratulations!
Your vulnerability report and proof of concept have been accepted and you will be receiving a bounty of USD $8,000.
I published KIS-2015-04 on September 11, 2015 and I received my bug bounty on September 21, 2015.
After a while, in late October 2015, I remembered about that information leakage bug I discovered back in February, and I wondered “Why don’t try to report this as well? Maybe I’m missing something out and I wrongly believe this isn’t a real security issue”. Actually I was missing something crucial, the fact that leveraging this vulnerability a remote unauthenticated attacker might be able to download order comments and other order-related information, potentially including Personally Identifiable Information or credit card data… What a bad “AppSec Guy” I am!!
I reported this vulnerability on October 29, 2015, including a Proof of Concept code, and a proposed patch for the vulnerability, which is exactly the same they used to fix the issue. I received a reply from the Magento Security Team on the very same day:
Thank you for your submission. We have logged ticket APPSEC-1171 to track this issue. We will reach out to you once our security engineers have validated this issue. Per the Magento Responsible Disclosure Guidelines, we ask that you do not disclose your finding to the public or to the media while we validate your submission with our security engineers.
After some months of silence, it was a wonderful Sunday afternoon when I noticed that some days earlier, specifically on January 20, 2016, the Magento team released SUPEE-7405 and new Magento versions which include fixes for several security-related issues, including “Information Disclosure in RSS feed – APPSEC-1171″. Consequently, I sent them another email asking whether there was any chance to get a bounty for reporting such a vulnerability (again!). I got their reply on February 1, 2016:
Hello Egidio, Congratulations!
Your vulnerability report and proof of concept have been accepted and you will be receiving a bounty of USD $9,000.
I received my bug bounty on February 12, 2016 and I published KIS-2016-02 on February 23, 2016. Actually there is a weird coincidence, because that very same day, only a few hours before publishing the advisory on my website, they pushed an update:SUPEE-7405 v1.1 patch bundle. It could be just a coincidence, however I found this very curious… don’t you?
Seeing my personal experience with the Magento bug bounty program (and even experiences from other security researchers), it looks like they truly believe in a “security through obscurity” methodology. I’m quite disappointed by the fact they tried to downplay the severity of my vulnerabilities, silently patching them after several months, without letting me know their progresses. However, what really disappoints me is that my vulnerabilities seem to be quite critical, specially considering they’re the only two classes of security bugs they’re willing to pay up to 10,000$ under their bug bounty program. I had to ping them several times in order to get my bounties, so I believe they tried to “obscure” and underevaluate my findings not only because of their “security through obscurity” methodology, but probably because they were also hoping I’d never noticed their advisories with my name and the vulnerabilities I reported, and never claimed my bounties for such findings?
Sucuri infosec researcher Peter Gramantik says carders are exploiting an unknown vulnerability to steal billing information from e-commerce sites that use eBay’s Magento platform.
Gramantik found an attack script that plunders POST data and identifies valuable payment data before storing it as an encrypted image file.
He says attackers appear to be exploiting a vulnerability in Magento core and demonstrate a strong understanding of the way the platform works.
A quarter of all Alexa top one million e-commerce sites are said to use Magento, making it a valuable target for attackers.
“It seems though that the attacker is exploiting a vulnerability in Magento core or some widely used module/extension,” Gramantik says .
“Using this vector, the attacker is able to inject malicious code into the Magento core file … the attacker gets the content of every POST request.
“The sad part is that you won’t know it’s affecting you until it’s too late, in the worst cases it won’t become apparent until they appear on your bank statements.”
Gramantik says the inclusion of a public key variable indicates the attacker is likely behind a family of credit card stealers.
The attack tool wipes trails clean and masks user agents in an attempt to avoid suspicion. It further modifies the creation timestamp of the image file in which billing information is stored and serves up a fake JPEG header.
“The attacker, however, is able to download the whole image file to decrypt the stolen contents using their public key, and now they have all the billing information processed by the Magento e-commerce website,” Gramantik says.
Variants have been found storing all POST data including login credentials to a gif image.
The security bod previously found a less surreptitious attack where billing information from the Magento billing module is exfiltrated over clear text.
A trio of vulnerabilities were recently patched in eBay’s Magento e-commerce web application that could have let attackers carry out a handful of exploits, including phishing, session hijacking, and data interception.
Hadji Samir, a researcher at the firm Vulnerability Lab dug up the problems earlier this year but it wasn’t until this week that they were disclosed, along with proof of concept logs and videos.
Perhaps the most troublesome issue fixed in the platform was a persistent filename vulnerability. A remote attacker could have injected their own script code into the application-side of the affected service module. This could have resulted in session hijacking, persistent phishing, persistent external redirects, along with “persistent manipulation of affected or connected module context,” according to the vulnerability disclosure.
A video that demonstrates the bug shows an attacker logging into Magento, creating a new message, and starting a session tamper to intercept session data. From there they can change the filename to a malicious payload of their choosing.
Samir also found a cross-site scripting (XSS) bug in the platform that could have made it easy for an attacker to remotely inject their own script code into the application-side of the vulnerable online-service module. This could have opened client side accounts up to theft by hijacking, client-side phishing, client-side external redirects and like the other bug, non-persistent manipulation of affected or connected service modules.
The last bug, a cross site request forgery (CSRF) vulnerability, could have allowed “unauthorized client-side application functions without secure validation or session token protection mechanism.” Basically an attacker could have intercepted user sessions and deleted their internal Magento messages without authorization.
Samir found the XSS bug in February and the other two March but Magento’s Developer Team held off until May to patch the issues. They were then publicly disclosed by Vulnerability Lab on Monday, Tuesday, and Wednesday, this week.
Earlier this year developers fixed a remote code execution bug in the platform dug up by Check Point that could have exposed customers’ credit card information, along with other personal data.
Web stores running on Magento, purchased from eBay in 2011, make up about 30 percent of the eCommerce market.