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.
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