Please note that republishing this article in full or in part is only allowed under the conditions described here.
While HTTP is defined in RFC2616 (HTTP/1.1) the specification does not address every tiny detail. This makes browsers behave similar for the usual HTTP traffic, but they differ in behavior regarding unusual or invalid traffic.
The same interpretation problems can be seen in security systems, e.g. Intrusion Detection Systems (IDS), proxies or firewalls. Thus differences in the interpretation of HTTP leave enough room for circumventing these security systems. This is especially true for systems, which just watch and maybe cut traffic, but not modify the traffic itself. And while active solutions like proxies might rewrite the traffic to avoid misinterpretation, not all solutions do it.
This article highlights some typical interpretation problems.
The following browsers and systems were tested:
- Firefox 21
- Google Chrome 27
- Opera 12.15
- MSIE (Internet Explorer) 8 and 10
- Rekonq 2.2.1
- Safari 5.1.1
- Bro 2.1
- Suricata 1.4.1
- squid 3.1.20/3.2.11
- AdBlockPlus Proxy Android
With chunked encoding (RFC2616, 3.6.1) the content length is not known in advance, but there will be a content length given for each data chunk and the responses closes with a chunk of length 0.
Chunked encoding is only defined for HTTP/1.1, thus a "Transfer-Encoding:chunked" header within an HTTP/1.0 response should be ignored. From the tested Web-Browsers Opera, Rekonq and Safari nevertheless interpreted the content as chunked, also the IDS Suricata and Bro and the squid proxy. Google Chrome, Firefox and MSIE instead followed the specification and did not interpret the content as chunked.
If one uses a Transfer-Encoding header of "chunked xx" or "xx chunked" Firefox, Safari, ABP Proxy and Suricata still interpret the content as chunked. Opera does not show this behavior with "xx chunked" but with "chunked xx". Safari instead also interprets "xchunked" and "chunkedx" as chunked and Suricata seems to interpret every value for Transfer-Encoding as chunked, even "chu". Bro does not interpret the content in all these cases as chunked, but strangely adds a newline to the extracted file in these cases.
While HTTP has no line length limitation it still supports folding of header lines over multiple lines similar to MIME. From the checked systems MSIE 8 and 10 are blind to folded lines and interpret the response as unchunked. Rekonq does not understand folding lines either, but considers the response invalid and only reports an error. All other systems have no problems.
It is not clear, how multipart MIME messages are useful in the context of HTTP, but there were several attempts made to put them into use:
- MSIE versions 6 and 7 support MHTML links, e.g. links of the form "mhtml:url!part", where the content of the url will be interpreted as a multipart/related message, where specific parts (defined by Content-Location header) can be accessed. This made it possible to put different resources into a single file and access them independly to speed up loading of pages. Because the implementation had lots of security problems and because MSIE 8 started to support data-URLs the feature was fortunatly abandoned with MSIE 8.
- Firefox still supports multipart/x-mixed-replace responsed, where each part gets displayed and then replaced with the next part. This feature is used in the web interface of some IP cameras to update the displayed image (using and endless MIME message)
But Firefox and Opera have some more surprises for us...
Both browsers take in some circumstances the last part of a multipart/mixed message as the real content. While this does not work with images in Firefox, it works with HTML displaying inside an iframe or file downloads. In Opera it additionaly works for images and Opera also supports the Content-Transfer-Encoding header, so that the data could be base64 encoded.
If the attacker has full control over the web server serving malware, it should be possible to adjust the payload, so that intermediate security systems will see a different payload than the victim browser.
- 2013/07/11 - contrary to what I said before squid, is as bad as the checked IDS in that it ignores the HTTP version when finding Transfer-Encoding chunked, e.g. it will also do chunked encoding for HTTP/1.0 responses. But at least it enforces this interpretation and changes the response, so that there is no ambigious interpretation possible for browsers behind squid.
- 2013/07/11 - I found log messages on the test server from a Chrome browser behind a Cisco IronPort, which indicate that at least Cisco IronPort WSA/7.5.1 ignores the HTTP version and also interprets "chunkedx" and "chunked xx" as "chunked". And like squid it enforces this interpretation in the protected systems by changing the response data accordingly.