|Forging HTTP request headers with Flash|
Amit Klein, July 2006|
Flash - Introduction
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();
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();
(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 22.214.171.124, running Flash 126.96.36.199 and Flash 188.8.131.52.
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 184.108.40.206, 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 220.127.116.11
// One Referer in IE 6.0 SP2, two Referers in FF 18.104.22.168
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  in the context of XmlHttpRequest):req.addRequestHeader("Host:","foobar.site");
This technique doesn't appear to work in FireFox 22.214.171.124.
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
This URL represents a Flash object that runs the following ActionScript code:
var req:LoadVars=new LoadVars();
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  (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.
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 () and HTTP Request Smuggling () - 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
 "Technology Breakdown" (Adobe website)
 "Macromedia Flash Player Version Penetration" (Adobe website)
 "Re: 'Exploiting the XmlHttpRequest object in IE' - paper by
Amit Klein" by Anonymous, BugTraq posting, September 27th, 2005
 "Unfiltered Header Injection in Apache 1.3.34/2.0.57/2.2.1"
by Thiago Zaninotti, BugTraq posting, May 8th, 2006
 "Re: Unfiltered Header Injection in Apache
1.3.34/2.0.57/2.2.1" by Amit Klein, BugTraq posting, May 18th, 2006
 "Client Side Trojans", Zope developers mailing list, May 2000
 "Cross Site Request Forgeries" by Peter Watkins, BugTraq posting, June 15th, 2001
 "Exploiting the XmlHttpRequest object in IE - Referrer
spoofing, and a lot more..." by Amit Klein, BugTraq posting, September 24th, 2005
 "Adobe Flash Player 9 Leads a New Generation of Dynamic Media and Rich Internet Applications" (Adobe website), June 28th, 2006
 "HTTP Request Smuggling" by Chaim Linhart, Amit Klein, Ronen Heled and Steve Orrin, June 6th, 2005