[REVS] Forging HTTP Request Headers with Flash ActionScript



The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion

The SecuriTeam alerts list - Free, Accurate, Independent.

Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html

- - - - - - - - -



Forging HTTP Request Headers with Flash ActionScript
------------------------------------------------------------------------


SUMMARY

This write-up presents the mechanism that can be used to send arbitrary
HTTP requests via Flash ActionScript. The security consequences for this
ability are also discussed here.

DETAILS

Flash - Introduction
-===================

Flash player is a very popular browser add-on from Adobe (actually, Flash
was invented by Macromedia, which was acquired
by Adobe). This write-up covers mostly Flash 7 and Flash 8, together
covering more than 94% of the Internet-enabled desktops (according to NPD
Online Survey conducted April 2006, quoted in Adobe's website [1], [2]).
Flash movies are delivered as SWF (ShockWave File) files. Adobe developed
a rich Javascript-like language called ActionScript to provide scripting
capabilities to Flash. One of the interesting features of ActionScript is
its ability to send HTTP requests to 3rd party sites through the browser
which invoked it. This is where Flash becomes interesting security-wise.
With Flash it is possible to shape an outgoing request to a 3rd party site
in ways not available from within "standard" Javascript. Specifically of
interest is Flash's ability to send arbitrary HTTP request headers with
outgoing HTTP requests.


Sending arbitrary HTTP request headers with Flash
-================================================

The following is ActionScript 2.0 syntax for sending out a GET request (in
this example, to http://www.vuln.site/some/page.cgi?p1=v1&p2=v2) with an
arbitrary HTTP header (Foo: Bar). This code works with Flash 7 and Flash 8
(probably with Flash 6 as well):

var req:LoadVars=new LoadVars();
req.addRequestHeader("Foo","Bar");
req.send("http://www.vuln.site/some/page.cgi?p1=v1&p2=v2";,
"_blank","GET");

A similar syntax will send POST request (with the same header, to the same
URL, and with body a=b&c=d):

var req:LoadVars=new LoadVars();
req.addRequestHeader("Foo","Bar");
req.decode("a=b&c=d");
req.send("http://www.vuln.site/some/page.cgi?p1=v1&p2=v2";,
"_blank","POST");

(note: the LoadVars.decode() method was added in Flash 7, yet it's
probably possible to compose an arbitrary POST body without it, so Flash 6
may be covered as well by this variant).

The request is sent from the browser invoking the Flash object. Any
cookies the browser normally sends, will be sent in those cases as well.
The browser's User-Agent is sent, as well as all browser standard headers.
HTTPS links are supported.

This was successfully demonstrated with Microsoft IE 6.0, Microsoft IE 6.0
SP2 and FireFox 1.5.0.4, running Flash 8.0.22.0 and Flash 7.0.19.0.

In IE, it is possible to overwrite some "normal" browser headers by simply
calling addRequestHeader with the new value. This is applicable to both
Referer and User-Agent. In FireFox 1.5.0.4, such headers, when used in
addRequestHeader() will be appended to the HTTP request header section.

// One UA in IE 6.0 SP2, two UAs in FF 1.5.0.4
req.addRequestHeader("User-Agent","Hacker/1.0");

// One Referer in IE 6.0 SP2, two Referers in FF 1.5.0.4
req.addRequestHeader("Referer","http://somewhere/";);

In IE, it is also possible to overwrite some more sensitive headers (e.g.
Host and Content-Length) by appending colon to the header name (this
technique was described in [3] in the context of XmlHttpRequest):

req.addRequestHeader("Host:","foobar.site");

This technique doesn't appear to work in FireFox 1.5.0.4.

Note: when the target URL is in the same domain with the Flash movie,
LoadVars may be used to read the HTTP response data, thus making LoadVars
the basis for many Flash-based AJAX-like frameworks (in analogy to
Javascript's XmlHttpRequest object).


The security implications
-========================

The ability of an attacker to force a victim's browser to send HTTP
requests to 3rd party sites with arbitrary HTTP request headers has impact
on our understanding of web application security - both on assessment of
security-related phenomena, and on the validity of some security
mechanisms.

It is important to understand that the attacks described here are (in
themselves) not cross-site scripting attacks, neither are they (strictly
speaking) any breach of cross-domain trust in the Flash object or between
the Flash object and the embedding HTML page. They merely make use of the
fact that it's possible to send requests from a Flash object to any URL,
with almost any HTTP headers the attacker needs. This in itself is the
problem, as it enables an attacker to send a link (to an HTML page
embedding a Flash object, or directly to a Flash object residing at the
attacker's website) that will cause a Flash object to be executed in the
victim's browser. This Flash object will send the HTTP request (with HTTP
headers chosen by the attacker) to a target website, and this in turn will
compromise the security of the browser (victim).

In other words, the implicit assumption made by many software developers
(and probably also by many security researchers) that most HTTP headers
cannot be forced to have arbitrary values by an attacker who serves data
to the victim browser is shown to be in error in this write-up.

Example 1 - The "Expect" header
-------------------------------

In [4], an injection problem was described wherein Apache 1.3.34, 2.0.57
and 2.2.1 are vulnerable to injecting HTML data (including malicious
Javascript code) through the Expect header. In [5], yours truly commented,
with respect to this issue, that "Regarding XSS This phenomenon is not XSS
per-se. Unless someone can show me how it is possible to force a browser
to send the Expect header to the target site". But using a Flash object,
the attack is trivial (the author is therefore answering his own question
here...). Consider a victim (browser) that clicks the following link:
http://www.evil.site/attack.swf

This URL represents a Flash object that runs the following ActionScript
code:

var req:LoadVars=new LoadVars();
req.addRequestHeader("Expect",
"<script>alert('gotcha!')</script>");
req.send("http://www.target.site/","_blank","GET";);

This ActionScript sends a request from the victim's browser, to the target
website (www.target.site) with an Expect header containing malicious HTML
(Javascript) code. If the target website runs a vulnerable version of
Apache, the net result is cross site scripting. So to be clear - there's a
working XSS attack against Apache 1.3.34, 2.0.57 and 2.2.1 (as long as the
client browser is IE or Firefox, and it supports Flash 6/7+). As noted in
[5], for Apache 2.0/2.2 the XSS response is returned by the server only
after the request timeout elapses (typically few minutes). Please note
though that a fix for the Apache server is available at all 3 branches (as
Apache 1.3.35, 2.0.58 and 2.2.2 respectively).

Example 2 - CSRF and Referer
----------------------------

CSRF (Cross Site Request Forgery) attack is in essence the ability of an
attacker to force a victim (browser) to effectively perform an action
(send HTTP request) in a target site. This concept emerged several times,
the first one probably on the Zope mailing list (as "Client Side Trojans",
[6], and another time on BugTraq, under its now de-facto standard name,
CSRF [7]. Both references suggest, among other measures, to rely on the
HTTP Referer header as evidence that the browser emits the HTTP request
from a link originating in the website. Indeed, considering the
capabilities of HTML+Javascript, effectively spoofing the Referer is
nearly impossible (one exception is [8], but it is effective only in a
limited subset of scenarios; e.g. it is not effective when HTTPS is used).
However, as can clearly be understood, with Flash this no longer holds,
and Referer can be spoofed for requests to HTTPS resources, all the while
having the browser send the site's cookies with the request. As
demonstrated above, both GET requests (with arbitrary host and query
parts) and POST requests (with arbitrary host and query parts, and body in
the standard Content-Type format of "application/x-www-form-urlencoded")
can be sent.

Note: there are many other reasons not to rely on the Referer header, and
this text is by no means the first one to warn against this practice.
It should be obvious that any reasonable header (and combinations thereof)
can be spoofed. In IE's case, the header provided by the attacker can
replace the browser-provided header (e.g. Referer).
In Firefox's case, the Referer spoofing technique may fail because Firefox
adds the header at the bottom of the HTTP request headers. Still, some web
applications may use the last value of the header, and as such be
vulnerable to this technique.

Plainly put, all this means that (reflective) cross site scripting attacks
that make use of HTTP request headers (e.g. Referer, User-Agent, Expect,
Host, Content-Type) to send the payload are now possible.


Flash 9
-======

Flash 9 was announced June 28th, 2006 [9] (i.e. less than a month ago). In
Flash 9, the techniques described above (for the LoadVars class) do not
work for any browser-provided header (e.g. User-Agent, Host and Referer),
nor probably for many "protected" headers such as Content-Length. Still,
headers like Expect can be sent, so some attacks (e.g. Example 1 above)
are still effective with Flash 9.


Limitations of the technique
-===========================

* The URL and the body part will always be URL-encoded. That is, it is
impossible (so it seems) to force SP, HT, CR and LF (and probably many
other characters) to appear in their raw form in the request URL and body.
* Only GET and POST methods can be used.
* In IE, only one instance of each header can be sent.

* At large, the header section cannot be completely controlled, e.g. an
attacker may have problems when attempting to send special characters
inside headers.

Partial solution
-===============

Notice the first limitation of the technique - it states that no raw CR
and LF can be placed in the body section. This means that the technique
cannot be used to send (POST) requests whose body complies with the
"multipart/form-data" content-type format (this format uses raw CRs and
LFs to mark headers and boundaries). In other words, a (POST) request
whose body is a valid "multipart/form-data" stream is guaranteed (as far
as today's knowledge extends) not to be sent from a Flash player. Web
application authors can therefore use HTML forms whose ENCTYPE attribute
is set to "multipart/form-data", and enforce that the submission contains
a valid multipart/form-data body. Once these mechanisms are in place, and
a request passes through, it is known not to originate from a Flash
player, so the attack
described here is irrelevant.

This solution is of course intrusive - both the HTML pages and the
receiving scripts must be altered to use (and enforce)
multipart/form-data. With some web development platforms, this is trivial,
yet in others (e.g. raw Perl, and ASP) it is not. Furthermore, in cases
such as Example 1 above, the HTTP headers are interpreted and used by the
(Apache) web server, and the control never reaches the web application
layer, so in such cases, this solution is not applicable.

Future directions
-================

HTTP Request Splitting ([8]) and HTTP Request Smuggling ([10]) - in IE +
Flash 7/8 it is possible to send a Content-Length header with any value.
This opens up an opportunity to perform HTTP Request Splitting attacks.
Also, injecting Transfer-Encoding header, or a second Content-Length
header may open up HTTP Request Smuggling. Further research is needed in
order to understand whether these directions lead to viable exploitation
techniques.

Flash 9 - while experiments show that Flash 9 is more strict concerning
which headers can be specified through LoadVars.addRequestHeader(), it's
ActionScript 3.0 language is much richer than ActionScript 2.0. As such,
it may open up several interesting opportunities at the HTTP level, e.g.
the ability to send various HTTP methods, not just GET and POST (WebDAV
anyone?). Flash 9 and ActionScript 3.0 should be studied better in order
to understand what is their potential with respect to crafting HTTP
requests.


Conclusions
-==========

Relying on the authenticity of HTTP request headers when they are sent
from a browser is not a good idea. Practically every header can be spoofed
if the client can be forced to run a malicious Flash movie, and this is
probably applicable to over 80% of the Internet desktops (i.e. Internet
desktops running IE + Flash 7/8). Consequently, the applicability of cross
site scripting attacks based on such headers, as well as cross site
request forgery attacks (against sites which protect themselves by
checking the Referer header) is higher than many people may perceive.

A partial solution to the latter case was suggested in the write-up,
however it is strongly tied to the specific technology used - Flash, and
as such may not provide any protection against variants that make use of a
different technology, or against developments in Flash itself. For
cross-site request forgery, therefore, different solutions, not relying on
Referer, should be considered.

References
-=========

[1] "Technology Breakdown" (Adobe website)
<http://www.adobe.com/products/player_census/flashplayer/tech_breakdown.html> http://www.adobe.com/products/player_census/flashplayer/tech_breakdown.html

[2] "Macromedia Flash Player Version Penetration" (Adobe website)
<http://www.adobe.com/products/player_census/flashplayer/version_penetration.html> http://www.adobe.com/products/player_census/flashplayer/version_penetration.html

[3] "Re: 'Exploiting the XmlHttpRequest object in IE' - paper by Amit
Klein" by Anonymous, BugTraq posting, September 27th, 2005
<http://www.securityfocus.com/archive/1/411823>
http://www.securityfocus.com/archive/1/411823

[4] "Unfiltered Header Injection in Apache 1.3.34/2.0.57/2.2.1" by Thiago
Zaninotti, BugTraq posting, May 8th, 2006
<http://www.securityfocus.com/archive/1/433280>
http://www.securityfocus.com/archive/1/433280

[5] "Re: Unfiltered Header Injection in Apache 1.3.34/2.0.57/2.2.1" by
Amit Klein, BugTraq posting, May 18th, 2006
<http://www.securityfocus.com/archive/1/434729>
http://www.securityfocus.com/archive/1/434729

[6] "Client Side Trojans", Zope developers mailing list, May 2000
<http://www.zope.org/Members/jim/ZopeSecurity/ClientSideTrojan>
http://www.zope.org/Members/jim/ZopeSecurity/ClientSideTrojan

[7] "Cross Site Request Forgeries" by Peter Watkins, BugTraq posting, June
15th, 2001 <http://www.tux.org/~peterw/csrf.txt>
http://www.tux.org/~peterw/csrf.txt

[8] "Exploiting the XmlHttpRequest object in IE - Referrer spoofing, and a
lot more..." by Amit Klein, BugTraq posting,
September 24th, 2005 <http://www.securityfocus.com/archive/1/411585>
http://www.securityfocus.com/archive/1/411585

[9] "Adobe Flash Player 9 Leads a New Generation of Dynamic Media and Rich
Internet Applications" (Adobe website), June 28th, 2006
<http://www.adobe.com/aboutadobe/pressroom/pressreleases/200606/062806Flash9.html> http://www.adobe.com/aboutadobe/pressroom/pressreleases/200606/062806Flash9.html

[10] "HTTP Request Smuggling" by Chaim Linhart, Amit Klein, Ronen Heled
and Steve Orrin, June 6th, 2005
<http://www.cgisecurity.com/lib/HTTP-Request-Smuggling.pdf>
http://www.cgisecurity.com/lib/HTTP-Request-Smuggling.pdf


ADDITIONAL INFORMATION

The information has been provided by ">Amit Klein.



========================================


This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@xxxxxxxxxxxxxx
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@xxxxxxxxxxxxxx


====================
====================

DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.



Relevant Pages

  • Write-up by Amit Klein: "Forging HTTP request headers with Flash"
    ... Forging HTTP request headers with Flash ... A similar syntax will send POST request (with the same header, ...
    (Bugtraq)
  • Re: SOAPACTIOn Missing!
    ... The SOAP 1.1 specification says this about the HTTP SOAPAction header; ... The SOAPAction HTTP request header field can be used to indicate the ...
    (microsoft.public.dotnet.framework.webservices)
  • Re: [PHP] HTTP request contents
    ... > HTTP request. ... the response can be sent by header() function. ... > But can I get the request of the client for server? ...
    (php.general)
  • Re: if-modified-since question (protocol problem?)
    ... request, but in response you are interested only if your request ... To base the decision on whether there is something 'new to show' would require knowledge about something 'old' - a cached resource. ... No Last-Modified header is sent in the response, ...
    (comp.infosystems.www.authoring.html)
  • Re: Controlling Javascript from server side
    ... declaration of the encoding of the message body. ... the expected encoding is always ISO/IEC ... 'true' means that the request must be handled asynchronously. ... (HTTP/1.x does not define such a request header for any request ...
    (comp.lang.javascript)