Re: allowHostHeaderMismatch option only works if the Host Header has an http or https prefix

2022-05-28 Thread Christopher Schultz

Ralph,

On 5/27/22 18:31, Ralph Atallah wrote:

I suspect that if we were to take the time to set up a proxy,
according to RFC7230, we would be able to get the absolute-form to
reach the Tomcat code and in that case, based on reading the
AbostractHttp11Processor class, I suspect the allowHostHeaderMismatch
will kick in and will behave correctly.  So I doubt that there is a
bug to report at this stage, at least not from my observation.

Thanks for the confirmation.


However, I wonder what all of this means.  Could it be that the Host
header injection or Host header attack issue can only occur when
absolute-form is used, i.e. mostly when proxies are set up?  Both you
and Mark stated that with origin-form there is nothing to compare the
Host header to, which makes sense.  Any thoughts on this assessment?


Well, if the client doesn't send a fully-qualified URL in the request 
line, then there is nothing to compare the Host header to.


I wonder what you think the "Host header attack" is, and how 
cross-checking against the URL would help.


Let's say the request looks like this:

GET http://example.com/some-resource
Host: attacker.com

Okay, this looks fishy and you can protect against it by rejecting the 
request. This is what Tomcat already does.


But how about this one?

GET http://attacker.com/some-resource
Host: attacker.com

What do you want to do, there? The request came to you, but it looks 
like it should have gone to attacker.com. If you want to reject it, you 
have to take other measures (which is what Mark was trying to explain in 
his responses).


No legitimate client is going to send you garbage, so you don't have to 
worry about e.g. Google Chrome sending you a bad request.


Anyone trying to attack you isn't going to provide convenient 
cross-checking information (e.g. host-in-request and 
host-in-Host-header) for you.


And finally, if you aren't validating the Host against a list of 
pre-defined allowed-hosts, then what's the point of even worrying about 
cross-checking?


If you aren't setting-up an allow-list, then how can you prevent 
requests like this from being processed (perhaps badly) by your application:


GET /some-resource
Host: attacker.com

?

I see under separate cover you have shown how you were able to use 
Tomcat's existing virtual-hosting configuration to explicitly allow only 
certain hosts. That seems like the best way for you to avoid mischief.


The primary attack vector I can see here is an intentionally malicious 
reverse proxy which is accepting requests at attacker.com and proxying 
them to YOUR service in order to trick users into sending information to 
them instead of you. If they can do that, they are already mounting a 
MitM against you and no amount of checking host headers is going to 
solve that problem.


-chris


-Original Message-
From: Christopher Schultz 
Sent: Friday, May 27, 2022 4:26 PM
To: users@tomcat.apache.org
Subject: Re: allowHostHeaderMismatch option only works if the Host Header has 
an http or https prefix

WARNING: This email originated from outside of CallMiner. Do not click any links or 
open any attachments unless you recognize the sender and know that the content is 
safe. Please report suspicious emails to: reportsuspiciousema...@callminer.com 


Mark,

On 5/27/22 3:13 AM, Mark Thomas wrote:

On 27/05/2022 02:00, Ralph Atallah wrote:

Hi Mark,

Thanks again for the prompt response.

You wrote below:  "If the original request only has a Host header,
then allowHostHeaderMismatch="false" isn't going to do anything
because there is no mismatch.".  I am not clear on what this means.
What should the match be between?  I thought the comparison for the
match was between the URL's hostname, i.e. "example.com" in the
http://example.com/myapp URL, and the Host header value which is
"attacker.com".  If that understanding is incorrect, please point me
in the right direction of what it should be.


The check is that the host in the request URI (if present) is
consistent with the Host header. Nothing more, nothing less.

HTTP requests may or may not include the host in the request URI.

The host named in the the headers of an HTTP request is completely
independent of the host name used to establish the connection to the
web server.


The AbstractHttp11Processor class does not get to the
allowHostHeaderMismatch detection code because the uriBC (URI
ByteChunk) that it reads is expecting an absolute URL
(http://example.com/myapp), but instead, it is getting a relative one
/myapp.  The reason I say the code expects an absolute URL is because
it checks for and "http" string at the beginning.  This makes me
wonder whether there is a setting that controls that URI format,
absolute or relative.


Your understanding of the HTTP protocol is flawed. You may wish to
read RFC 7230. Specifically:

https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.1
and

RE: allowHostHeaderMismatch option only works if the Host Header has an http or https prefix

2022-05-27 Thread Ralph Atallah
Hi Chris,

I suspect that if we were to take the time to set up a proxy, according to 
RFC7230, we would be able to get the absolute-form to reach the Tomcat code and 
in that case, based on reading the AbostractHttp11Processor class, I suspect 
the allowHostHeaderMismatch will kick in and will behave correctly.  So I doubt 
that there is a bug to report at this stage, at least not from my observation.

However, I wonder what all of this means.  Could it be that the Host header 
injection or Host header attack issue can only occur when absolute-form is 
used, i.e. mostly when proxies are set up?  Both you and Mark stated that with 
origin-form there is nothing to compare the Host header to, which makes sense.  
Any thoughts on this assessment?

Thanks,
Ralph

-Original Message-
From: Christopher Schultz  
Sent: Friday, May 27, 2022 4:26 PM
To: users@tomcat.apache.org
Subject: Re: allowHostHeaderMismatch option only works if the Host Header has 
an http or https prefix

WARNING: This email originated from outside of CallMiner. Do not click any 
links or open any attachments unless you recognize the sender and know that the 
content is safe. Please report suspicious emails to: 
reportsuspiciousema...@callminer.com 


Mark,

On 5/27/22 3:13 AM, Mark Thomas wrote:
> On 27/05/2022 02:00, Ralph Atallah wrote:
>> Hi Mark,
>>
>> Thanks again for the prompt response.
>>
>> You wrote below:  "If the original request only has a Host header, 
>> then allowHostHeaderMismatch="false" isn't going to do anything 
>> because there is no mismatch.".  I am not clear on what this means.
>> What should the match be between?  I thought the comparison for the 
>> match was between the URL's hostname, i.e. "example.com" in the 
>> http://example.com/myapp URL, and the Host header value which is 
>> "attacker.com".  If that understanding is incorrect, please point me 
>> in the right direction of what it should be.
>
> The check is that the host in the request URI (if present) is 
> consistent with the Host header. Nothing more, nothing less.
>
> HTTP requests may or may not include the host in the request URI.
>
> The host named in the the headers of an HTTP request is completely 
> independent of the host name used to establish the connection to the 
> web server.
>
>> The AbstractHttp11Processor class does not get to the 
>> allowHostHeaderMismatch detection code because the uriBC (URI
>> ByteChunk) that it reads is expecting an absolute URL 
>> (http://example.com/myapp), but instead, it is getting a relative one 
>> /myapp.  The reason I say the code expects an absolute URL is because 
>> it checks for and "http" string at the beginning.  This makes me 
>> wonder whether there is a setting that controls that URI format, 
>> absolute or relative.
>
> Your understanding of the HTTP protocol is flawed. You may wish to 
> read RFC 7230. Specifically:
>
> https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.1
> and
> https://datatracker.ietf.org/doc/html/rfc7230#section-5.3
>
> Requests with the URI in origin-form do not include a host in the URI.
>
> The purpose of allowHostHeaderMismatch is to ensure that when the 
> request URI is in absolute-form that the request URI is consistent 
> with the Host header.
>
>> Regarding the addition of a filter that you propose, we have an 
>> existing one in our application, but by the time it is reached, the 
>> URL that we see is already http://attacker.com/myapp, i.e. already 
>> "redirected".
>
> There has been no redirect. The URI reported is a combination of the 
> Host header and request URI received.
>
>>  Technically we could check there against a whitelist, but this would 
>> make the solution less out-of-the box, and more needy of user 
>> configuration in our app.  We prefer an out-of-the-box secure solution.
>>
>> Any thoughts on the above?
>
> What you want isn't possible.

Actually, I think what Ralph is requesting is exactly what Tomcat is providing 
in the form of allowHostHeaderMismatch (when set to false).

The only problem is that Ralph is saying it's not working because the URI in 
the request doesn't contain a hostname *at all* (because it's optional). So 
there is nothing to check. Browsers don't bother to send the optional 
protocol/hostname/port/etc and instead send the relative URI -- relative to the 
Host header (no coincidentally).

If you (Ralph) can reproduce this with wc or telnet where you can force the URI 
to be absolute *and* provide a conflicting Host header, then I think you have 
grounds for a bug report.

> If you want requests to be rejected unless the Host header is on a 
> user defined allow list (presumably the set of DNS names defined for 
> the host), then you are going to have to provide a means for the user 
> to provide that configuration.

I don't think it being requested, here. It may be an aim of their application 
to do such things, but that wasn't a part of the initial request 

RE: allowHostHeaderMismatch option only works if the Host Header has an http or https prefix

2022-05-27 Thread Ralph Atallah
Hi Mark,

Thank you for your help.  It took some digging to fully understand the nuances 
in your answers below.  Here are some pointers to anyone who experiences the 
same issue in the future and to whom these pointers might be helpful.

1. Although I had previously visited the link to the RFC7230 page 
https://datatracker.ietf.org/doc/html/rfc7230#section-5.3 re-reading more 
closely and with Mark's emphasis on it highlighted the fact that most of the 
time, the request line will be of the origin-form, while the absolute-form will 
be mainly observed when proxies are used.  This was a very important 
explanation of why we never saw the absolute-form reach the 
AbstractHttp11Processor code in our test environment.

2. "The approach requiring the minimal input from the app and where the 
container does most of the work is the one where you define a Host element in 
server.xml with the name and optional aliases for the host names that are 
acceptable and configure the default host (that handles all requests to other 
hosts) to reject all other requests."   This statement was key to the solution:

Our server.xml looked like this:



  
 ...

We simply had to change the defaultHost value to something else than 
"localhost", i.e. a value that will be rejected  (e.g. "defaulthost").   The 
Host's name as well as any Aliases defined within that tag would be the only 
hosts accepted, whether in the URL request or in the Host header request.   The 
rejection would respond with a 404 Not Found error.

Thanks,
Ralph

-Original Message-
From: Mark Thomas  
Sent: Friday, May 27, 2022 3:13 AM
To: users@tomcat.apache.org
Subject: Re: allowHostHeaderMismatch option only works if the Host Header has 
an http or https prefix

WARNING: This email originated from outside of CallMiner. Do not click any 
links or open any attachments unless you recognize the sender and know that the 
content is safe. Please report suspicious emails to: 
reportsuspiciousema...@callminer.com 


On 27/05/2022 02:00, Ralph Atallah wrote:
> Hi Mark,
>
> Thanks again for the prompt response.
>
> You wrote below:  "If the original request only has a Host header, then 
> allowHostHeaderMismatch="false" isn't going to do anything because there is 
> no mismatch.".  I am not clear on what this means.  What should the match be 
> between?  I thought the comparison for the match was between the URL's 
> hostname, i.e. "example.com" in the http://example.com/myapp URL, and the 
> Host header value which is "attacker.com".  If that understanding is 
> incorrect, please point me in the right direction of what it should be.

The check is that the host in the request URI (if present) is consistent with 
the Host header. Nothing more, nothing less.

HTTP requests may or may not include the host in the request URI.

The host named in the the headers of an HTTP request is completely independent 
of the host name used to establish the connection to the web server.

> The AbstractHttp11Processor class does not get to the allowHostHeaderMismatch 
> detection code because the uriBC (URI ByteChunk) that it reads is expecting 
> an absolute URL (http://example.com/myapp), but instead, it is getting a 
> relative one /myapp.  The reason I say the code expects an absolute URL is 
> because it checks for and "http" string at the beginning.  This makes me 
> wonder whether there is a setting that controls that URI format, absolute or 
> relative.

Your understanding of the HTTP protocol is flawed. You may wish to read RFC 
7230. Specifically:

https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.1
and
https://datatracker.ietf.org/doc/html/rfc7230#section-5.3

Requests with the URI in origin-form do not include a host in the URI.

The purpose of allowHostHeaderMismatch is to ensure that when the request URI 
is in absolute-form that the request URI is consistent with the Host header.

> Regarding the addition of a filter that you propose, we have an existing one 
> in our application, but by the time it is reached, the URL that we see is 
> already http://attacker.com/myapp, i.e. already "redirected".

There has been no redirect. The URI reported is a combination of the Host 
header and request URI received.

>  Technically we could check there against a whitelist, but this would make 
> the solution less out-of-the box, and more needy of user configuration in our 
> app.  We prefer an out-of-the-box secure solution.
>
> Any thoughts on the above?

What you want isn't possible. If you want requests to be rejected unless the 
Host header is on a user defined allow list (presumably the set of DNS names 
defined for the host), then you are going to have to provide a means for the 
user to provide that configuration.

The approach requiring the minimal input from the app and where the container 
does most of the work is the one where you define a Host element in server.xml 
with the name and optional aliases for 

Re: allowHostHeaderMismatch option only works if the Host Header has an http or https prefix

2022-05-27 Thread Christopher Schultz

Mark,

On 5/27/22 3:13 AM, Mark Thomas wrote:

On 27/05/2022 02:00, Ralph Atallah wrote:

Hi Mark,

Thanks again for the prompt response.

You wrote below:  "If the original request only has a Host header, 
then allowHostHeaderMismatch="false" isn't going to do anything 
because there is no mismatch.".  I am not clear on what this means.  
What should the match be between?  I thought the comparison for the 
match was between the URL's hostname, i.e. "example.com" in the 
http://example.com/myapp URL, and the Host header value which is 
"attacker.com".  If that understanding is incorrect, please point me 
in the right direction of what it should be.


The check is that the host in the request URI (if present) is consistent 
with the Host header. Nothing more, nothing less.


HTTP requests may or may not include the host in the request URI.

The host named in the the headers of an HTTP request is completely 
independent of the host name used to establish the connection to the web 
server.


The AbstractHttp11Processor class does not get to the 
allowHostHeaderMismatch detection code because the uriBC (URI 
ByteChunk) that it reads is expecting an absolute URL 
(http://example.com/myapp), but instead, it is getting a relative one 
/myapp.  The reason I say the code expects an absolute URL is because 
it checks for and "http" string at the beginning.  This makes me 
wonder whether there is a setting that controls that URI format, 
absolute or relative.


Your understanding of the HTTP protocol is flawed. You may wish to read 
RFC 7230. Specifically:


https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.1
and
https://datatracker.ietf.org/doc/html/rfc7230#section-5.3

Requests with the URI in origin-form do not include a host in the URI.

The purpose of allowHostHeaderMismatch is to ensure that when the 
request URI is in absolute-form that the request URI is consistent with 
the Host header.


Regarding the addition of a filter that you propose, we have an 
existing one in our application, but by the time it is reached, the 
URL that we see is already http://attacker.com/myapp, i.e. already 
"redirected".


There has been no redirect. The URI reported is a combination of the 
Host header and request URI received.


 Technically we could check there against a whitelist, but this would 
make the solution less out-of-the box, and more needy of user 
configuration in our app.  We prefer an out-of-the-box secure solution.


Any thoughts on the above?


What you want isn't possible.


Actually, I think what Ralph is requesting is exactly what Tomcat is 
providing in the form of allowHostHeaderMismatch (when set to false).


The only problem is that Ralph is saying it's not working because the 
URI in the request doesn't contain a hostname *at all* (because it's 
optional). So there is nothing to check. Browsers don't bother to send 
the optional protocol/hostname/port/etc and instead send the relative 
URI -- relative to the Host header (no coincidentally).


If you (Ralph) can reproduce this with wc or telnet where you can force 
the URI to be absolute *and* provide a conflicting Host header, then I 
think you have grounds for a bug report.



If you want requests to be rejected unless the Host header is on a
user defined allow list (presumably the set of DNS names defined for
the host), then you are going to have to provide a means for the user
to provide that configuration.


I don't think it being requested, here. It may be an aim of their 
application to do such things, but that wasn't a part of the initial 
request ("prevent host header injection" -- which is very strangely worded).


-chris

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: allowHostHeaderMismatch option only works if the Host Header has an http or https prefix

2022-05-27 Thread Mark Thomas

On 27/05/2022 02:00, Ralph Atallah wrote:

Hi Mark,

Thanks again for the prompt response.

You wrote below:  "If the original request only has a Host header, then allowHostHeaderMismatch="false" 
isn't going to do anything because there is no mismatch.".  I am not clear on what this means.  What should the 
match be between?  I thought the comparison for the match was between the URL's hostname, i.e. "example.com" 
in the http://example.com/myapp URL, and the Host header value which is "attacker.com".  If that 
understanding is incorrect, please point me in the right direction of what it should be.


The check is that the host in the request URI (if present) is consistent 
with the Host header. Nothing more, nothing less.


HTTP requests may or may not include the host in the request URI.

The host named in the the headers of an HTTP request is completely 
independent of the host name used to establish the connection to the web 
server.



The AbstractHttp11Processor class does not get to the allowHostHeaderMismatch detection 
code because the uriBC (URI ByteChunk) that it reads is expecting an absolute URL 
(http://example.com/myapp), but instead, it is getting a relative one /myapp.  The reason 
I say the code expects an absolute URL is because it checks for and "http" 
string at the beginning.  This makes me wonder whether there is a setting that controls 
that URI format, absolute or relative.


Your understanding of the HTTP protocol is flawed. You may wish to read 
RFC 7230. Specifically:


https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.1
and
https://datatracker.ietf.org/doc/html/rfc7230#section-5.3

Requests with the URI in origin-form do not include a host in the URI.

The purpose of allowHostHeaderMismatch is to ensure that when the 
request URI is in absolute-form that the request URI is consistent with 
the Host header.



Regarding the addition of a filter that you propose, we have an existing one in our 
application, but by the time it is reached, the URL that we see is already 
http://attacker.com/myapp, i.e. already "redirected".


There has been no redirect. The URI reported is a combination of the 
Host header and request URI received.



 Technically we could check there against a whitelist, but this would make the 
solution less out-of-the box, and more needy of user configuration in our app.  
We prefer an out-of-the-box secure solution.

Any thoughts on the above?


What you want isn't possible. If you want requests to be rejected unless 
the Host header is on a user defined allow list (presumably the set of 
DNS names defined for the host), then you are going to have to provide a 
means for the user to provide that configuration.


The approach requiring the minimal input from the app and where the 
container does most of the work is the one where you define a Host 
element in server.xml with the name and optional aliases for the host 
names that are acceptable and configure the default host (that handles 
all requests to other hosts) to reject all other requests.


Mark



Thanks,
Ralph

-Original Message-
From: Mark Thomas 
Sent: Thursday, May 26, 2022 12:21 PM
To: users@tomcat.apache.org
Subject: Re: allowHostHeaderMismatch option only works if the Host Header has 
an http or https prefix

WARNING: This email originated from outside of CallMiner. Do not click any links or 
open any attachments unless you recognize the sender and know that the content is 
safe. Please report suspicious emails to: reportsuspiciousema...@callminer.com 


On 26/05/2022 14:29, Ralph Atallah wrote:

Hi Mark,

What we are trying to do is to prevent Host header attacks by ensuring that the host name 
in the http request URL always matches the "Host" header in the request.  If it 
does not, we are supposed refuse the request and respond with 400 Bad Request as per 
OWASP recommendations.   Here are some examples:

Normal request
 GET http://example.com/myapp
 Host: example.com
 Expected response:  200 OK

Request with a host header attack
 GET http://example.com/myapp
 Host: attacker.com
 Expected response:  400 Bad Request

The AbstracktHttp11Processor.java class seems to be doing exactly that in the 
code snippet below:

 if (allowHostHeaderMismatch) {
   // The requirements of RFC 2616 are being
   // applied. If the host header and the request
   // line do not agree, the request line takes
   // precedence
   hostValueMB = headers.setValue("host");
   hostValueMB.setBytes(uriB, uriBCStart + pos, slashPos - pos);
   } else {
// The requirements of RFC 7230 are being
// applied. If the host header and the request
// line do not agree, trigger a 400 response.
badRequest("http11processor.request.inconsistentHosts");
   }

However, this portion of the code is never reached for the reason mentioned in 
the 

RE: allowHostHeaderMismatch option only works if the Host Header has an http or https prefix

2022-05-26 Thread Ralph Atallah
Hi Mark,

Thanks again for the prompt response. 

You wrote below:  "If the original request only has a Host header, then 
allowHostHeaderMismatch="false" isn't going to do anything because there is no 
mismatch.".  I am not clear on what this means.  What should the match be 
between?  I thought the comparison for the match was between the URL's 
hostname, i.e. "example.com" in the http://example.com/myapp URL, and the Host 
header value which is "attacker.com".  If that understanding is incorrect, 
please point me in the right direction of what it should be.

The AbstractHttp11Processor class does not get to the allowHostHeaderMismatch 
detection code because the uriBC (URI ByteChunk) that it reads is expecting an 
absolute URL (http://example.com/myapp), but instead, it is getting a relative 
one /myapp.  The reason I say the code expects an absolute URL is because it 
checks for and "http" string at the beginning.  This makes me wonder whether 
there is a setting that controls that URI format, absolute or relative.

Regarding the addition of a filter that you propose, we have an existing one in 
our application, but by the time it is reached, the URL that we see is already 
http://attacker.com/myapp, i.e. already "redirected".  Technically we could 
check there against a whitelist, but this would make the solution less 
out-of-the box, and more needy of user configuration in our app.  We prefer an 
out-of-the-box secure solution.

Any thoughts on the above?

Thanks,
Ralph

-Original Message-
From: Mark Thomas  
Sent: Thursday, May 26, 2022 12:21 PM
To: users@tomcat.apache.org
Subject: Re: allowHostHeaderMismatch option only works if the Host Header has 
an http or https prefix

WARNING: This email originated from outside of CallMiner. Do not click any 
links or open any attachments unless you recognize the sender and know that the 
content is safe. Please report suspicious emails to: 
reportsuspiciousema...@callminer.com 


On 26/05/2022 14:29, Ralph Atallah wrote:
> Hi Mark,
>
> What we are trying to do is to prevent Host header attacks by ensuring that 
> the host name in the http request URL always matches the "Host" header in the 
> request.  If it does not, we are supposed refuse the request and respond with 
> 400 Bad Request as per OWASP recommendations.   Here are some examples:
>
> Normal request
> GET http://example.com/myapp
> Host: example.com
> Expected response:  200 OK
>
> Request with a host header attack
> GET http://example.com/myapp
> Host: attacker.com
> Expected response:  400 Bad Request
>
> The AbstracktHttp11Processor.java class seems to be doing exactly that in the 
> code snippet below:
>
> if (allowHostHeaderMismatch) {
>   // The requirements of RFC 2616 are being
>   // applied. If the host header and the request
>   // line do not agree, the request line takes
>   // precedence
>   hostValueMB = headers.setValue("host");
>   hostValueMB.setBytes(uriB, uriBCStart + pos, slashPos - pos);
>   } else {
>// The requirements of RFC 7230 are being
>// applied. If the host header and the request
>// line do not agree, trigger a 400 response.
>badRequest("http11processor.request.inconsistentHosts");
>   }
>
> However, this portion of the code is never reached for the reason mentioned 
> in the previous email.
>
> By the time the request reaches our application, the 
> HttpServletRequest.getRequestURL() returns  http://attacker.com/myapp instead 
> of http://example.com/myapp
> We have enabled the AccessLogValve in server.xml in the hope to see the URL 
> that reaches tomcat, but it seems that we only get the relative URL there, 
> never the absolute one, i.e. we only see /myapp when we print %u for example.
>
> Any tips in this area would be much appreciated.

If the original request only has a Host header, then
allowHostHeaderMismatch="false" isn't going to do anything because there
is no mismatch.

If you want to reject requests that have a Host header that isn't one
you recognize then there are multiple options:

- write a Filter
- write a Valve
- configure a Host (or several) for the requests you want to allow and
   deploy an ROOT to the default host that rejects everything else.

Mark



> Ralph
>
> -Original Message-
> From: Mark Thomas 
> Sent: Thursday, May 26, 2022 3:24 AM
> To: users@tomcat.apache.org
> Subject: Re: allowHostHeaderMismatch option only works if the Host Header has 
> an http or https prefix
>
> WARNING: This email originated from outside of CallMiner. Do not click any 
> links or open any attachments unless you recognize the sender and know that 
> the content is safe. Please report suspicious emails to: 
> reportsuspiciousema...@callminer.com 
> 
>
> On 26/05/2022 02:20, Ralph Atallah wrote:
>> Hi,
>>
>> We use Tomcat 

Re: allowHostHeaderMismatch option only works if the Host Header has an http or https prefix

2022-05-26 Thread Mark Thomas

On 26/05/2022 14:29, Ralph Atallah wrote:

Hi Mark,

What we are trying to do is to prevent Host header attacks by ensuring that the host name 
in the http request URL always matches the "Host" header in the request.  If it 
does not, we are supposed refuse the request and respond with 400 Bad Request as per 
OWASP recommendations.   Here are some examples:

Normal request
GET http://example.com/myapp
Host: example.com
Expected response:  200 OK

Request with a host header attack
GET http://example.com/myapp
Host: attacker.com
Expected response:  400 Bad Request

The AbstracktHttp11Processor.java class seems to be doing exactly that in the 
code snippet below:

if (allowHostHeaderMismatch) {
  // The requirements of RFC 2616 are being
  // applied. If the host header and the request
  // line do not agree, the request line takes
  // precedence
  hostValueMB = headers.setValue("host");
  hostValueMB.setBytes(uriB, uriBCStart + pos, slashPos - pos);
  } else {
   // The requirements of RFC 7230 are being
   // applied. If the host header and the request
   // line do not agree, trigger a 400 response.
   badRequest("http11processor.request.inconsistentHosts");
  }

However, this portion of the code is never reached for the reason mentioned in 
the previous email.

By the time the request reaches our application, the 
HttpServletRequest.getRequestURL() returns  http://attacker.com/myapp instead 
of http://example.com/myapp
We have enabled the AccessLogValve in server.xml in the hope to see the URL 
that reaches tomcat, but it seems that we only get the relative URL there, 
never the absolute one, i.e. we only see /myapp when we print %u for example.

Any tips in this area would be much appreciated.


If the original request only has a Host header, then 
allowHostHeaderMismatch="false" isn't going to do anything because there 
is no mismatch.


If you want to reject requests that have a Host header that isn't one 
you recognize then there are multiple options:


- write a Filter
- write a Valve
- configure a Host (or several) for the requests you want to allow and
  deploy an ROOT to the default host that rejects everything else.

Mark




Ralph

-Original Message-
From: Mark Thomas 
Sent: Thursday, May 26, 2022 3:24 AM
To: users@tomcat.apache.org
Subject: Re: allowHostHeaderMismatch option only works if the Host Header has 
an http or https prefix

WARNING: This email originated from outside of CallMiner. Do not click any links or 
open any attachments unless you recognize the sender and know that the content is 
safe. Please report suspicious emails to: reportsuspiciousema...@callminer.com 


On 26/05/2022 02:20, Ralph Atallah wrote:

Hi,

We use Tomcat 7.0.109 and Tomcat 8.5 in our Tomcat based webapp deployments and 
we have a new requirement to prevent Host Header injection.  The 
allowHostHeaderMismatch option seems the perfect answer to this issue.  
However, configuring it in our environment, i.e. in the server.xml connector 
tag still does not seem to make it work.

Debugging the code, we see that the check for this setting is never even 
reached in the 
org.apache.coyote.http11.AbstractHttp11Processor.prepareRequest() method.  The 
reason is in the code snippet below:

   ByteChunk uriBC = request.requestURI().getByteChunk();
   byte[] uriB = uriBC.getBytes();
   if (uriBC.startsWithIgnoreCase("http", 0)) {
 ...
  if (allowHostHeaderMismatch) {
 ...
  }
}

uriBC does not contain the full URL such as http://localhost:8080/myapp, but rather only 
the /myapp path, so that if (uriBC.startsWithIgnoreCase("http", 0)) condition 
is never met.

We are probably missing something very basic, and would really appreciate some 
guidance.


I suspect that allowHostHeaderMismatch doesn't do what you think it does.

Exactly what problem are you trying to solve when so say you want to prevent "Host 
header injection"?

Mark

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org


-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



RE: allowHostHeaderMismatch option only works if the Host Header has an http or https prefix

2022-05-26 Thread Ralph Atallah
Hi Mark,

What we are trying to do is to prevent Host header attacks by ensuring that the 
host name in the http request URL always matches the "Host" header in the 
request.  If it does not, we are supposed refuse the request and respond with 
400 Bad Request as per OWASP recommendations.   Here are some examples:

Normal request
   GET http://example.com/myapp
   Host: example.com
   Expected response:  200 OK 

Request with a host header attack
   GET http://example.com/myapp
   Host: attacker.com
   Expected response:  400 Bad Request

The AbstracktHttp11Processor.java class seems to be doing exactly that in the 
code snippet below:

   if (allowHostHeaderMismatch) {
 // The requirements of RFC 2616 are being
 // applied. If the host header and the request
 // line do not agree, the request line takes
 // precedence
 hostValueMB = headers.setValue("host");
 hostValueMB.setBytes(uriB, uriBCStart + pos, slashPos - pos);
 } else {
  // The requirements of RFC 7230 are being
  // applied. If the host header and the request
  // line do not agree, trigger a 400 response.
  badRequest("http11processor.request.inconsistentHosts");
 }

However, this portion of the code is never reached for the reason mentioned in 
the previous email.

By the time the request reaches our application, the 
HttpServletRequest.getRequestURL() returns  http://attacker.com/myapp instead 
of http://example.com/myapp
We have enabled the AccessLogValve in server.xml in the hope to see the URL 
that reaches tomcat, but it seems that we only get the relative URL there, 
never the absolute one, i.e. we only see /myapp when we print %u for example.  

Any tips in this area would be much appreciated.
Ralph

-Original Message-
From: Mark Thomas  
Sent: Thursday, May 26, 2022 3:24 AM
To: users@tomcat.apache.org
Subject: Re: allowHostHeaderMismatch option only works if the Host Header has 
an http or https prefix

WARNING: This email originated from outside of CallMiner. Do not click any 
links or open any attachments unless you recognize the sender and know that the 
content is safe. Please report suspicious emails to: 
reportsuspiciousema...@callminer.com 


On 26/05/2022 02:20, Ralph Atallah wrote:
> Hi,
>
> We use Tomcat 7.0.109 and Tomcat 8.5 in our Tomcat based webapp deployments 
> and we have a new requirement to prevent Host Header injection.  The 
> allowHostHeaderMismatch option seems the perfect answer to this issue.  
> However, configuring it in our environment, i.e. in the server.xml connector 
> tag still does not seem to make it work.
>
> Debugging the code, we see that the check for this setting is never even 
> reached in the 
> org.apache.coyote.http11.AbstractHttp11Processor.prepareRequest() method.  
> The reason is in the code snippet below:
>
>   ByteChunk uriBC = request.requestURI().getByteChunk();
>   byte[] uriB = uriBC.getBytes();
>   if (uriBC.startsWithIgnoreCase("http", 0)) {
> ...
>  if (allowHostHeaderMismatch) {
> ...
>  }
> }
>
> uriBC does not contain the full URL such as http://localhost:8080/myapp, but 
> rather only the /myapp path, so that if (uriBC.startsWithIgnoreCase("http", 
> 0)) condition is never met.
>
> We are probably missing something very basic, and would really appreciate 
> some guidance.

I suspect that allowHostHeaderMismatch doesn't do what you think it does.

Exactly what problem are you trying to solve when so say you want to prevent 
"Host header injection"?

Mark

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: allowHostHeaderMismatch option only works if the Host Header has an http or https prefix

2022-05-26 Thread Mark Thomas

On 26/05/2022 02:20, Ralph Atallah wrote:

Hi,

We use Tomcat 7.0.109 and Tomcat 8.5 in our Tomcat based webapp deployments and 
we have a new requirement to prevent Host Header injection.  The 
allowHostHeaderMismatch option seems the perfect answer to this issue.  
However, configuring it in our environment, i.e. in the server.xml connector 
tag still does not seem to make it work.

Debugging the code, we see that the check for this setting is never even 
reached in the 
org.apache.coyote.http11.AbstractHttp11Processor.prepareRequest() method.  The 
reason is in the code snippet below:

  ByteChunk uriBC = request.requestURI().getByteChunk();
  byte[] uriB = uriBC.getBytes();
  if (uriBC.startsWithIgnoreCase("http", 0)) {
...
 if (allowHostHeaderMismatch) {
...
 }
}

uriBC does not contain the full URL such as http://localhost:8080/myapp, but rather only 
the /myapp path, so that if (uriBC.startsWithIgnoreCase("http", 0)) condition 
is never met.

We are probably missing something very basic, and would really appreciate some 
guidance.


I suspect that allowHostHeaderMismatch doesn't do what you think it does.

Exactly what problem are you trying to solve when so say you want to 
prevent "Host header injection"?


Mark

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org