<<< Date Index >>>     <<< Thread Index >>>

Write-up by Amit Klein: "Forging HTTP request headers with Flash"



           Forging HTTP request headers with Flash

                   Amit Klein, July 2006


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

[2] "Macromedia Flash Player Version Penetration" (Adobe website) 
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

[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

[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

[6] "Client Side Trojans", Zope developers mailing list, May 2000
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

[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

[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

[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