You are viewing avatraxiom

To The Side

HTTP Response Splitting: A Common, But Frequently Unknown, Security Issue

Recently, there were two security issues discovered in Bugzilla that would fall under the category of HTTP Response Splitting attacks. Although this is a common issue in web applications, many developers are unaware of it, its consequences, or how to protect their applications from it.

In short, here's what you need to know:

Never allow unsanitized user data into HTTP headers.

Most of the time, if you're using some HTTP framework, it should be handling this for you. So mostly you just need to make sure that you have a good HTTP library that security-checks its header output properly. But if you're printing headers directly to the user, as plain text (as I've seen many PHP apps do), you do need to be concerned about this.

In particular, it's most important that you never allow any character that might be considered a "newline" into your HTTP headers. To understand why, and what could be dangerous about this, you need to know a little bit about HTTP. Let's say that we're sending a response to the user that looks like this:

200 OK
X-My-Header: some_user_data
Content-Type: text/html; charset=UTF-8

<html><head><title<Hello World!</title><body></body></html>

Okay, pretty simple. This is a page that has "Hello World!" as the title, and no content. Harmless. However, what's that X-My-Header: some_user_data there? Let's imagine that some_user_data can be anything that the user input, and he inputs a string that looks like:

some data;
Content-Type: text/html; charset=UTF-8

<script type="text/javascript">all_your_base();</script>

Now, your response looks like:

200 OK
X-My-Header: some data;
Content-Type: text/html; charset=UTF-8

<script type="text/javascript">all_your_base();</script>

Content-Type: text/html; charset=UTF-8

<html><head><title<Hello World!</title><body></body></html>

And I could have inserted anything! It's not just like a normal Cross-Site Scripting vulnerability, where I can only insert a small dangerous piece of HTML into an already-existing page. I could insert any HTML, any script, or any content at all. That content could be an ActiveX control for Internet Explorer, it could be some other content that your system is already configured to open automatically--anything. I'm not limited just to HTML or JavaScript. There's also a good chance that any Set-Cookie headers will become a part of the body instead of being part of the headers, too, so I can steal cookies even if they're marked "httponly".

For the most part, this vulnerability is prevented if you never allow people to insert a CR or LF character into headers. There's no good reason to allow inserting those characters directly into a single header, so you should be pretty safe to just completely deny those characters in HTTP headers generated by your application.

-Max
Tags: ,

Comments

Good one

You beat me to it :)

I am going to blog on a bunch of security issues I found in Google pages - and HTTP response splitting will make an appearance as well. But I am going to write something about how HTTP response splitting can be exploited in redirects.

I was actually pretty surprised to see this kind of vulnerability on google.com - unlike XSS it is easily solved on the API level, so it is typically only seen where web developers are simply ignorant. But ignorance is never the issue when we are talking about Google.

Re: Good one

That sounds like it could be an interesting blog, for sure.

Yeah, honestly I think that it's just that a large number of developers really are ignorant about it. It's funny, people are aware of the problem when they put together RFC2822 emails, but for some reason they never think about it with HTTP headers--I think because they assume that their HTTP framework will "do the right thing" and convert or forbid the newlines. Even I wasn't aware of the problem until it was reported to us--I thought that CGI.pm would simply handle the situation properly instead of just allowing through all sorts of dangerous input.

-Max

Re: Good one

For whatever reason, PHP only fixed the problem in the framework only recently. CGI.pm does indeed escape newlines - but it doesn't look like they do it for security reasons (only some headers included and they don't look at LF). So I would say that the framework developers are largely ignorant.

Re: Good one

Yeah. CGI.pm does it as of 3.50--we reported the issue to them and they released a fix. (They now die on invalid vertical whitespace in header values.) But before they were not doing it in a complete fashion.

I think that overall, what this vuln needs is a LOT more awareness in the developer community.

-Max
Yeah, and if for any reason you want to allow custom headers, make sure that the header name is something acceptable plus a colon, don't tolerate blank lines, and add at least one space and/or tab after every line break.
Oh right, that's a good point too! I'm pretty sure header names are restricted to a pretty limited set of characters, so validating them against the RFC would be a good idea.
Oh, I suppose testing for /[A-Z][A-Za-z-]*:/, even if too lax, would be sufficient; but no space before the colon, and my point was: you can accept linebreaks if you add whitespace after each of them (to make "continuation" headers); and no empty lines (I'm not sure if a line containing one or more whitespace would terminate the headers, but there's no point in having them).
Yeah, continuation headers are theoretically allowed, but I'm not aware of any single-line limit in any HTTP client or server anywhere (unlike with email), so I really don't think there's any point in supporting them.

-Max