In my last post, Pentesting Adobe Flex Applications with a Custom AMF Client, I described how one could write a client using Python and PyAMF to perform manual penetration testing of Flex applications. The example application I focused on utilized RemoteObjects and communicated via binary AMF encoded messages, a common roadblock for security testers. If you are new to penetration testing Flex applications, I suggest reading my previous post to familiarize yourself with Flex and the techniques I discussed.
In this post, I'll show how you can exploit Flex applications that use BlazeDS to gain access to internal networks and other hosts behind the firewall. BlazeDS is a Java-based remoting server that allows developers to utilize existing application logic and web services in Flex applications. The following also applies to applications that use Adobe LiveCycle Data Services ES.
A common insecure configuration that we encounter when assessing Flash applications is an insecure crossdomain.xml policy file (usually hosted within a web site's root directory). By default, a Flash application hosted on domain A cannot access resources from domain B unless domain B has configured their cross-domain policy to allow domain A. More often than not, the cross domain policy file has been configured to allow the entire world access rather than a specific list of trusted domains. Now, assuming the cross domain policy file has been secured, developers of Flex applications that consume data from external web services must now incorporate this restriction into their design. This makes it difficult to develop Flex applications that will be hosted on multiple, possibly untrusted domains.
Enter BlazeDS. To get around the restrictions imposed by cross-domain policy files, BlazeDS allows developers to configure "Proxy Services". Using Proxy Services, BlazeDS will make calls to remote service destinations on behalf of the Flex application. BlazeDS Proxy Services allows Flex applications to consume SOAP and Web Services hosted on other domains without the need for a cross-domain policy. A common use case for proxy services is to allow external access to internally hosted web services via a specified destination. A typical proxy service is configured like so (see BlazeDS Developer Guide for more detail):
# contents of WEB-INF\flex\proxy-config.xml:
<service id="proxy-service" class="flex.messaging.services.HTTPProxyService">
In the proxy-config.xml above, we have two destinations defined: web-service and soap-service. If you look closely, the soap property has an asterisk (wildcard) defined. This property can define an absolute domain and path, however like cross-domain policies, an asterisk permits BlazeDS to make requests to any hosts it can reach on the network that match this property. This is a common occurrence, due in part to sample configuration files supplied with BlazeDS and lack of awareness on part of those responsible for securing the application server. In more secure configurations, this property is set to a strict domain or path (such as the web-service destination).
If you want to build a Flex client that communicates with Proxy Services, you'll need to familiarize yourself with the following objects (refer to the Flex Language Reference for more information):
- mx.rpc.http.HTTPService (url)
- mx.messaging.messages.HTTPRequestMessage (url)
- mx.rpc.soap.WebService (endpointURI)
- mx.rpc.soap.mxml.SOAPService (endpointURI)
- mx.messaging.messages.SOAPMessage (url)
Without further ado, I'd like to introduce Blazentoo, a tool I developed to exploit such functionality. With Blazentoo, you can exploit insecurely configured Proxy Services and browse internal websites, potentially those on trusted corporate networks. Just recently I was working on an assessment and I was able to successfully compromise an internal application via an exposed BlazeDS server – as this wasn't the first (or last) time, I decided it was time to build Blazentoo.
- AMF/HTTP endpoint (the message broker servlet that flex requests are routed to)
- The "destination" id (if this is left blank, the DefaultHTTP destination is used)
- An optional "channel" id (leave blank if unknown)
If using SOAP, you'll need to know the following additional information:
- A SOAP Action associated with the destination id, and/or
- URL of the WSDL (required if no destination id is defined)
Below is a screenshot of Blazentoo in action. Note that the URL being accessed in this example is "http://localhost/". This could just as easily have been an internal IP address or hostname.
You can download Blazentoo from our tools page.