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 <ma...@apache.org>
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 
<mailto: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 <ma...@apache.org>
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 
<mailto: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


---------------------------------------------------------------------
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

Reply via email to