Exploit-DB #38652
Description: Google AdWords 6.2.0 API client libraries - XML eXternal Entity Injection
Type: webapps
Platform: php
Date: 2015-11-07
Author: Dawid Golunski

Exploit:
# Date: 06.11.2015
# Exploit Author: Dawid Golunski
# Vendor Homepage: https://developers.google.com/adwords/api/docs/clientlibraries
# Software Link: https://github.com/googleads/googleads-php-lib
# Version: Google AdWords API client libraries - XML eXternal Entity Injection (XXE)


=============================================
- Release date: 06.11.2015
- Discovered by: Dawid Golunski
- Severity: Medium/High
=============================================

 
I. VULNERABILITY
-------------------------

Google AdWords API client libraries   -    XML eXternal Entity Injection (XXE)

Confirmed in googleads-php-lib <= 6.2.0 for PHP, AdWords libraries: 
googleads-java-lib for Java, and googleads-dotnet-lib for .NET are also likely
to be affected.

 
II. BACKGROUND
-------------------------

- AdWords API

"The AdWords API is a collection of web services that you can use to build 
applications that manage AdWords accounts and their associated campaign data.
While the AdWords API is based on SOAP 1.1, high-level client libraries are 
provided to help you develop applications more quickly."

AdWords API client libraries are available for different platforms
such as PHP, .NET, Java etc. 

These can be found at:

https://developers.google.com/adwords/api/docs/clientlibraries
 
III. INTRODUCTION
-------------------------

As Google AdWords is based on SOAP protocol that uses XML to transfer the data,
client API libraries should have necessary preventions against XML eXternal 
Entity injection attacks. However, an independent research found the necessary
preventions to be lacking in several Google AdWords API client libraries,
which could allow XXE attacks on applications/servers that make use of them.

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 (when an 'expect' PHP module is installed) lead to command 
execution.

IV. DESCRIPTION
-------------------------
 
This advisory will focus on PHP version of the AdWords API client library.
Other versions of the client library such as .NET and Java seem to be 
vulnerable in a similar way.

googleads-php-lib contains the following function which queries WSDL from the 
remote google adwords server:

---[ build_lib/WSDLInterpreter/WSDLInterpreter.php ]---

  protected function loadWsdl($wsdlUri, $proxy = null) {
    // Set proxy.
    if ($proxy) {
      $opts = array(
          'http' => array(
              'proxy' => $proxy,
              'request_fulluri' => true
          )
      );
      $context = stream_context_get_default($opts);
      libxml_set_streams_context($context);
    }

    $this->dom = new DOMDocument();
    $this->dom->load($wsdlUri,
        LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NOENT|LIBXML_XINCLUDE);

    $this->serviceNamespace =
        $this->dom->documentElement->getAttribute('targetNamespace');
  }

-------------------------------------------------------

The function connects to the API endpoint to get the WSDL document describing
the functionality of the AdWords web service in XML.

For security reasons Google AdWords API can only be accessed via HTTPS. 
However, the above code does not set appropriate SSL settings on the 
https:// stream context. It fails to assign Certificate Authority (CA),
and turn the verify_peer option to ON.
It uses the stream_context_get_default() to get the default context,
which on all PHP versions below PHP 5.6.x (see references below) does not 
validate the CA by default. 

Because of this, applications using the AdWords API library may be tricked into 
retrieving data from untrusted sources pretending to be adwords.google.com.

The above code does not provide any XXE injection attack prevention.
It does not disable external entity processing. To make it worse,
it specifically enables it via the LIBXML parameters provided to the 
dom->load() function so an XXE injection attack would work even on
systems that have the newest and fully patched version of libxml library 
which does not process the entities by default.

Another vulnerable part of the application is located in the code:

---[ src/Google/Api/Ads/Common/Util/XmlUtils.php ]---

  public static function GetDomFromXml($xml) {
    set_error_handler(array('XmlUtils', 'HandleXmlError'));
    $dom = new DOMDocument();
    $dom->loadXML($xml,
        LIBXML_DTDLOAD | LIBXML_DTDATTR | LIBXML_NOENT | LIBXML_XINCLUDE);
    restore_error_handler();
    return $dom;
  }

-----------------------------------------------------

which is used by the AdsSoapClient class to process SOAP requests. It
also activates the ENTITY processing even if libxml parser is set to
ingore them by default. AdsSoapClient can be configured to verify SSL peer
in SSL communication via the settings INI file but this option is set to 
off by default.

These SSL settings, and the XML ENTITY processing combined make applications 
using the AdWords API vulnerable to XXE injection attacks. 

For the attack to be successful, an attacker needs to
perform a MitM attack to impersonate adwords.google.com server (eg. via DNS 
poisoning/spoofing/proxy attacks, ARP spoofing, etc.) to inject malicious 
XML input.

 
V. PROOF OF CONCEPT
-------------------------
 
Below is a test application that makes use of the PHP Google AdWords API 
library.

The application simply connects to the AdWords API endpoint to retrieve the 
WSDL document.

---[ testAPI.php ]---

<?php
// Test application reading WSDL from Google AdWords 

set_include_path('./build_lib/WSDLInterpreter/');
require_once 'WSDLInterpreter.php';

$wsdlUri = 'https://adwords.google.com/api/adwords/cm/v20150