2

So I was tasked with researching a problem that was identified by an Acunetix web security scan.

Here are the details about the scan:
Host_header_attack
Automated Detection of Host Header Attacks

I can't post more than two links yet as I don't have enough reputation, but the skeletonscribe reference on the first of the above links goes into more detail about the exploit and seems to be the main source on the subject.

The suggested workarounds suggest the use of 'dummy' default virtual hosts and applications using SERVER_NAME instead of using the Host header. These suggestions are great when talking about a true origin server, but not so much when you are using a reverse proxy.

Our web site that is being scanned by Acunetix is set up as an application server sitting behind a reverse proxy. In our case, the reverse proxy is iPlanet, but I have confirmed the same behaviour in Apache 2.4.7 with mod_proxy. Here is how it works, and why it triggers the Acunetix scan.

When a request is made using an absolute URI (As the scanner does), the server is, according to RFC spec, meant to ignore the Host header and instead use the host that is within the absolute URI. This is the behaviour that we see and as a result, the correct virtual host is selected, even if the Host header has an incorrect/malicious value. So far so good.

The problem arises when the reverse proxy then passes this request on to the back-end origin server. When it does this, it passes the original Host header along with the request. If the Host header has an incorrect or malicious value, this will then get passed back to the origin server. If the origin server does not implement virtual hosts, then it does not need to verify that the Host header is correct.

The result of this is that any application running on the origin web/app server that tries to use the value of the Host header will be using the malicious host value. Using the SERVER_NAME is of no use in this instance as the server name (or true host) of the site does not get forwarded by the reverse proxy and the origin server still responds with the Host header value. Using UseCanonicalName and the ServerName directive here is also of no use, as you need the server name from the original request, which could be more than one value.

This 'attack' was identified in 2013, but I can't find a whole lot of information on it that doesn't just re-iterate the details from the above references. It's not a common problem because HTTP clients do not send absolute URI's unless they are talking to forward proxy servers. This means that all regular requests will be relative URI's and this problem then goes away (Malicious Host headers then get stuck at the 'dummy' or default virtual host on the reverse proxy).

I did create a workaround, whereby the reverse proxy actively sets the Host header to the SERVER_NAME before the request is sent to the back-end. This works, but I worry if it may be a solution that goes against bet practices/standards. Would setting the Host header like this break something? We brainstormed this, but I can't think of a scenario where it would. I will be opening a call to Oracle tomorrow to get feedback from them.

It seems to me that this may be such a fringe case, that it's just an oversight in the two web server products that I tried, but I can't imagine something would go so long without being addressed. I must be missing something.

Sorry it's so long, but, any ideas? :) The 'question' part of this essay would be this:

  1. Would my workaround above be a good solution or would it break things?
  2. Is there a known solution for this problem?
masegaloeh
  • 17,978
  • 9
  • 56
  • 104
Tom17
  • 333
  • 3
  • 6

2 Answers2

3

Your reverse proxy is supposed to be correcting the Host: header for you by default. That it doesn't do so is a bug and should be reported to its developer(s).

From RFC 7230 section 5.4:

When a proxy receives a request with an absolute-form of request-target, the proxy MUST ignore the received Host header field (if any) and instead replace it with the host information of the request-target. A proxy that forwards such a request MUST generate a new Host field-value based on the received request-target rather than forward the received Host field-value.

Note that the previous version of this RFC, RFC 2616, was much less specific. It only said:

An HTTP/1.1 proxy MUST ensure that any request message it forwards does contain an appropriate Host header field that identifies the service being requested by the proxy.

The behavior of your proxy cannot be said to conform to either the old or the new specification.

In the meantime, your workaround is fine, since it introduces the correct behavior.

Michael Hampton
  • 237,123
  • 42
  • 477
  • 940
  • Awesome! This is the answer I was looking for :) It's interesting that the Apache I tested does not conform. The _default_ behaviour of Apache is not to preserve the Host: header at all. Only when you turn `ProxyPreserveHost` on do you see the non-compliant behaviour I described. It seems to me that the Apache mod_proxy default is also non-compliant as it is my understanding that the RFC language is quite strict with the use of the word 'MUST'. I will grab and build a fresh Apache and test with that to confirm those findings and create a bug report if necessary. Not done that before, eek! – Tom17 Feb 06 '15 at 14:08
  • I'm not sure if it's acceptable to ask this in here, or if I should ask a new question, but this wording of the RFC never made sense to me, so I just glossed over it. But I am looking at this in detail now and it just doesn't jive with me. "If the authority component is missing or undefined for the target URI, then a client MUST send a Host header field with an empty field-value.". This means if there is no authority (i.e. it's a relative URI) then the host header should have no value? This makes no sense to me. – Tom17 Feb 08 '15 at 14:04
  • You've misinterpreted that section. Even relative URIs have an authority component. But it's also not relevant to this question. – Michael Hampton Feb 08 '15 at 18:13
  • I sure did. I get it now - it can be like legalese that stuff! Also, I realised it was off-topic (I was working through the RFC again and got stuck there), hence asking if it was acceptable to ask. Moot now though. Thanks again. – Tom17 Feb 10 '15 at 03:31
  • It's more like programming. You have to account for virtually everything. RFCs are design documents, after all, specifications meant for writing programs... – Michael Hampton Feb 10 '15 at 03:33
  • Well, yes. I guess I explained myself badly :) I was not paying enough detail to definitions of words further up in the doc(I was thinking of request-target when I read target URI), hence referring to it that way, but yes, that's a programming thing really, defining things accurately. Sorry i'm off topic :) – Tom17 Feb 10 '15 at 13:56
0

I have the same issue to fix, Acunetix reported this vulnerability - I do not have a reverse proxy, but I came up the same solution, I explicitly set the Host header in the vHost so it is always what i want. However running the scan again shows that the issue is still there.

I used Postman and cURL to verify my solution and noted that the malicious Host or X-Forwarded-Host headers were no longer getting echoed but Acunetix is still showing the vulnerability as there...

I implemented 2 solutions:

1) Created a catchall vHost ... 2) Explicitly set the Host header in my server vHost

Point 1 is to protect against merely changing the Host header to prevent Apache from passing the request to the first name based vHost and point 2 sorts the X-Forwarded-Host modification.

What else is there?

Apache 2.4 Ubuntu 14.04.5

Paul Barclay
  • 131
  • 1