views:

291

answers:

5

I just got hammered on a Security Audit by Deloitte on behalf of SFDC. Basically we use flex and communicate via AMF. We use FluorineFX for this (as opposed to LCDS and Blaze). We are being told that because the AMF response is not encoded and that someone can manipulate the AMF parameters and insert Javascript that this is a XSS vulnerability. I'm struggling to understand how the AMF response back, which could echo the passed in JS in an error message, can be executed by the browser or anything else for that matter. I'm quite experienced with XSS with HTML and JS but seeing it get tagged with AMF was a bit of a surprise. I'm in touch with FluorineFx team and they are perplexed as well.

I'd be surprised to see an AMF library encode the response data, Fluorine surely does not. It would seem though that security applications like PortSwigger and IBM AppScan are including this type of test in their tool chest. Have you run into this vulnerability with AMF and can you explain how the XSS issue can manifest itself? Just curious. I need to either argue my way out of this if an argument exists or patch the hole. Given the AMF usage with Flex I thought you might have some insight.

Additional information ...

So A little more on this from the actual vendor, PortSwigger. I posed the question to them and net, net, they concede this type of attack is extremely complicated. Initially they are classifying this as a High Severity security issue but I think their tune is changing now. I thought I'd post the content of their response for you all as I think the perspective is interesting none-the-less.

--- From PortSwigger on the issue ---

Thanks for your message. I think the answer is that this is potentially a vulnerability, but is not trivial to exploit.

You're right, the issue wouldn't arise when the response is consumed by an AMF client (unless it does something dumb), but rather if an attacker could engineer a situation where the response is consumed by a browser. Most browsers will overlook the HTTP Content-Type header, and will look at the actual response content, and if it looks at all like HTML will happily process it as such. Historically, numerous attacks have existed where people embed HTML/JS content within other response formats (XML, images, other application content) and this is executed as such by the browser.

So the issue is not so much the format of the response, but rather the format of the request required to produce it. It's not trivial for an attacker to engineer a cross-domain request containing a valid AMF message. A similar thing arises with XML requests/responses which contain XSS-like behaviour. It's certainly possible to create a valid XML response which gets treated by the browser as HTML, but the challenge is how to send raw XML in the HTTP body cross-domain. This can't be done using a standard HTML form, so an attacker needs to find another client technology, or browser quirk, to do this. Historically, things like this have been possible at various times, until they were fixed by browser/plugin vendors. I'm not aware of anything that would allow it at the moment.

So in short, it's a theoretical attack, which depending on your risk profile you could ignore altogether or block using server-side input validation, or by encoding the output on the server and decoding again on the client.

I do think that Burp should flag up the AMF request format as mitigation for this issue, and downgrade the impact to low - I'll get this fixed.

Hope that helps.

Cheers PortSwigger

--- more info on audit ---

what portSwigger does is not necessarily mess with binary payload, what they do is mess with the actual AMF parameters that are posted to the handler to direct the request. For example here is a snippet from the audit and it shows part of the AMF response to a request ...

HTTP/1.1 200 OK
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
P3P: CP="CAO PSA OUR"
Content-Type: application/x-amf
Vary: Accept-Encoding
Expires: Tue, 06 Apr 2010 18:02:10 GMT
Date: Tue, 06 Apr 2010 18:02:10 GMT
Connection: keep-alive
Content-Length: 2595

......../7/onStatus.......
.SIflex.messaging.messages.ErrorMessage.faultCode.faultString
.faultDetail.rootCause.extendedData.correlationId.clientId.destination
.messageId.timestamp.timeToLive    body.headers.#Server.Processing..kFailed 
to locate the requested type 
com.Analytics.ca.Services.XXX5c2ce<script>alert(1)</script>9ccff0bda62..
....I506E8A27-8CD0-598D-FF6E-D4490E3DA69F.Id95ab281-d83b-4beb-abff-c668b9fd42d5
..fluorine.I04165c8e-f878-447f-a19a-a08cbb7def2a.A.q..@............
.        DSId.Aeb5eeabcbc1d4d3284cbcc7924451711.../8/onRes
...[SNIP]...

note the "alert" script in there ... what they did was appended some script enclosed JS to one of the parameters that are passed containing the method to call namely 'com.Analytics.ca.Services.XXX'. By doing so the JS came back in an error message but there are a lot of things that would have to happen for that JS to get anywhere close to executing. Seems an indirect threat at best.

-- Security Auditor's latest perspective --

I’ve discussed with the larger team and we all believe it’s a valid attack. As PortSwigger mentions in his first paragraph, while theoretically since you set the content-type to x-amf, and would hope it won’t render in the browser, most browsers will ignore this request and render it anyway. I think the vendors are relying heavily on the fact that the content-type is set; however popular browsers like IE and some versions of Safari will ignore this.

The attack can easily be triggered by exploiting CSRF or any other form of initiating an XSS attack.

+1  A: 

I can't explain how someone would take advantage of this "vulnerability".

But, can you solve the issue to their satisfaction by passing data over an HTTPS connection instead of straight HTTP? Assuming you have an SSL certificate installed on your server and HTTPS enabled, this should be a minor change in the services-config.xml file that you compile into your Flex Application.

I pinged an Adobe colleague of mine in hopes that he can offer more insight.

www.Flextras.com
thanks for response. I added a bunch more to the post above that might shed more light on what is being tested. We are 100% ssl and pretty strongly fortified in that regard, it would take a lot to even reproduce the scenario that they are testing but these audits are rarely that black and white in my experience.
Dean Skelton
+6  A: 
  1. It could not be a JavaScript injection, as what in the Flash Player would interpret JS? The flash community would be ecstatic if we had native JS or even json support in the player. There is no eval function for actionscript let alone javascript

  2. Let's assume they meant you could inject it with actionscript. The AMF protocol does not send code, it sends data models in the form of primitive types or generic or typed objects. The worst thing that could happen is that they analyze your model and add additional data. This would be amazingly difficult to do as you would not be able to inject the data but would have to parse all the data, add the new data, parse it back and keep the AMF headers. Because AMF uses references in it's data serialization which means that when duplicate object types you would have had to of seen the first object. The reference is then an offset which means little chance of adding code but only changing values to existing parameters.

  3. The remote object has a response handler that is checking for the data types and expects to bind those data types to ui components or whatever your code does. If those data types are wrong you will get an error. If the AMF response sequence number is wrong you will get an error. If anything is not perfectly formed in the amf datagram you will get an error.

  4. Remote object automatically retry. If the "injecting" code takes to long Flex will resend a message and invalidate the one that took to long.

Just my two cents. As an AMF developer I have frequently wished it was easy to screw with the amf datagram for debugging and testing. Unfortunately you will get an error.

Wade Arnold

Wade Arnold
+1 listen to this man, he is highly experienced with AMF. Basically it is impossible to do an JS XSS attack with AMF. It may be possible if you did some really insane coding (extracting data from AMF, passing it out to JS, and calling an eval() on it...but that is so unlikely it's silly). Deloitte basically doesn't know what they're talking about, I'm sorry if you had to pay huge sacks of $$$ to them for the 'audit'.
davr
I'm +1ing Wade too. For those that don't know; he was the project lead on AMF PHP for a while and was deeply involved in the Zend AMF project. You'd be hard pressed to find a non-Adobe Engineer who knows AMF better than he.
www.Flextras.com
Great answer Wade! One thing to add... HTTPS can be used as the transport for AMF which would protect against man-in-the-middle attacks.
James Ward
Just noticed that Jeffry pointed out the HTTPS thing too. +1 to him as well. :)
James Ward
Added some additional information to Post. I happend to reach the security vendor and their comments on the issue are now on the post.We are definately using SSL so I feel secure there. This threat is very very remote at best but audit is treating it as a high security issue which I think is the problem.
Dean Skelton
Thanks all, added a little more to the post showing a snip from the audit report. You will see above that actually what they are doing is messing with the posted parameters to the AMF engine that tell it how to route the payload. You can see the response coming back with Javascript in there. I guess the question is, "Is it the AMF vendors responsibility to encode responses of this nature?" I have to admit while the threat is slight, it does not look good to see this coming back in a response as a coder could mistakenly mishandle this response message, although it would take carelessness.
Dean Skelton
James/Wade, I have further added a response I received from Salesforce.com regarding the XSS vulnerability. I have added that to my post as well. Curious what you think, they are adamant that this can be exploited.
Dean Skelton
A: 

I don't know how possible it is to alter data within an AMF response stream, but you might want to ensure that your endpoints cannot be manipulated through communication with the browser and/or JavaScript. Check out this article under the Malicious data injection section.

adamcodes
This is very helpful and really lines up with the types of things we are doing to avoid security threats of this nature. In regards to AMF specifically, PortSwigger's BurpScanner will actually mess with parameters that are passed to the AMF handler. For example, it might replace a "method name" parameter with some valid javascript tags which results in an error since the method cannot be found. The AMF response can then emit back the supplied JS in it's error mesage. If you mishandle that response you could expose an XSS if you send the response message to the HTML page as an example.
Dean Skelton
+1  A: 

You seem to have answered your own queries here.

So you have a server side implementation that takes the arguments to an amf function call and includes the input data somewhere in the returned output.

I appreciate that this is largely a theoretical attack as it involves getting the payload to be rendered by the browser and not into an amf client. Other vulnerabilities in browsers/plugins may be required to even enable this scenario. Maybe a CSRF post via the likes of a gateway.php or similar would make this pretty easy to abuse, as long as the browser processed the output as html/js.

However, unless you need the caller to be able to pass-through angle brackets into the response, just html-encode or strip them and this attack scenario dissapears.

This is interesting though. Normally one would perform output-encoding solely for the expected consumer of the data, but it is interesting to consider that the browser could often be a special case. This really is one hell of an edge-case, but i'm all for people getting into the habit of sanitising and encoding their untrusted inputs.

This reminds me, in many ways, to the way that cross-protocol injection can be used to abuse the reflection capabilities of protocols such as smtp to acheive XSS in the browser. See http://i8jesus.com/?p=75

Cheekysoft
Thanks for the response. I think this is the way to go and you are correct that the safest path to side-stepping this is to sanitize the inputs. For now I'll try intercepting the request and encoding the AMF parameters before they are passed back to the server, this hopefully should take care of this. This was definitely a surprise to encounter this on an audit ... I want to get this behind me. Hope my pain helps others. :)
Dean Skelton
I think there are easier ways to solve this problem than encoding amf parameters. See my response below.
sri
A: 

I think it is a valid attack scenario. A related attack is GIFAR, where the JVM is fooled to treat a gif file as a jar. Also, I don't think output encoding is the right way to solve the problem.

The premise of the attack is to fool the browser into thinking the AMF response is HTML or Javascript. This is possible because of a feature called MIME Type Detection, which is essentially the browser saying "Developers may not know about content-types, I will play god and (possibly incorrectly) figure out the MIME type".

In order for this to work, the following need to hold true -

  1. The attacker should be able to make a GET or POST request to your AMF server using HTML techniques like <script> or <frame> or an <a> tag. Techniques like XmlHttpRequest or Flash or Silverlight don't count.
  2. The attacker should be able to insert malicious content into the first 256 or so bytes of the response. Additionally, this malicious content should be able to trick the browser in thinking that the rest of the response is really javascript or html.

So, how do you prevent it?

It is best to ensure the attacker cannot make a request in the first place. A very simple and effective way is to add a http request header while making the AMF request, check its existence on the server and deny the request if absent. The value can be a hard-coded value and need not be secret. This works, because there is no known method of adding a custom request header via standard html techniques. You can do so via XmlHttpRequest or flash or silverlight, but then the browser will not interpret the content-type for you, so its okay.

Now, I don't know much about AMF, but if it is already adding a request header - then this attack scenario is not possible. If it isn't, its trivial to add one.

HTML escaping the content is not a good solution. Allegedly, there are various ways to trick the browser into thinking the response is actually HTML. In other words, the malicious input need not be well formed HTML. Try a google search on mime sniffing, you should be able to find various ways to trick the browser.

sri
Here are two references that explain the general problem - http://code.google.com/p/browsersec/wiki/Part2#Survey_of_content_sniffing_behaviors and http://code.google.com/p/doctype/wiki/ArticleContentSniffing
sri