Tim,

Thank you for your reply.

Your code sends a 421 if the SNI and host header don't match.
Is this the recommended behavior? The RFC is pretty thin here:

"   Since it is possible for a client to present a different server_name
   in the application protocol, application server implementations that
   rely upon these names being the same MUST check to make sure the
   client did not present a different name in the application protocol."
(from https://datatracker.ietf.org/doc/html/rfc6066#section-11.1 )

My initial idea was to simply pave over any incoming headers with the SNI:

>       http-request set-header Host %[ssl_fc_sni] if { ssl_fc_has_sni }

This wouldn't abort the request with a 421 but I am not sure if I MUST abort it 
to be compliant.

Regarding domain fronting, I thought I might be able to have the cake and eat 
it, too if I still allowed it but only prevented it for mTLS
Requests. Maybe like this:

>       http-request set-header Host %[ssl_fc_sni] if { ssl_c_used }


What are your thoughts?

Best regards,
Dom

On 24.06.21, 16:05, "Tim Düsterhus" <t...@bastelstu.be> wrote:

    Dominik,

    On 6/24/21 3:29 PM, Froehlich, Dominik wrote:
    > Not sure if you would call this a security issue, hence I am asking this 
on the mailing list prior to opening a github issue:

    This is also known as "Domain Fronting" 
    (https://en.wikipedia.org/wiki/Domain_fronting). It's not necessarily a 
    security issue and in fact might be the desired behavior in certain 
    circumstances.

    > I’ve noticed that it is really easy to bypass the check on client 
certificates of a domain when the client can present a valid certificate for 
another domain.

    Indeed. I also use client certificates for authentication and I'm aware 
    of this issue. That's why I validate that the SNI and Host match up for 
    my set up. In fact I added the 'strcmp' converter to HAProxy just for 
    this purpose. The documentation for 'strcmp' also gives an explicit 
    example on how to use it to prevent domain fronting:

    > http-request set-var(txn.host) hdr(host)
    > # Check whether the client is attempting domain fronting.
    > acl ssl_sni_http_host_match ssl_fc_sni,strcmp(txn.host) eq 0

    https://cbonte.github.io/haproxy-dconv/2.4/configuration.html#7.3.1-strcmp

    My full rules look like this:

    >   # Verify that SNI and Host header match
    >   http-request   set-var(txn.host)    hdr(host)
    >   http-request   deny deny_status 400 unless { req.hdr_cnt(host) eq 1 }
    >   http-request   deny deny_status 421 unless { 
ssl_fc_sni,strcmp(txn.host) eq 0 }

    -

    > […]
    > 
    > My questions:
    > 
    >    *   HAproxy does seem to treat SNI (L5) and HTTP Host Header (L7) as 
unrelated. Is this true?

    Yes.

    >    *   Applications offloading TLS to HAproxy usually trust that mTLS 
requests coming in are validated correctly. They usually don’t revalidate the 
entire certificate again and only check for the subject’s identity. Is there a 
way to make SNI vs host header checking more strict?

    Yes, see above.

    >    *   What’s the best practice to dispatch mTLS requests to backends? 
I’ve used a host header based approach here but it shows the above 
vulnerabilities.

    You *must* use the 'Host' header for routing. Using the SNI value for 
    routing is even more unsafe. But you also must validate that the SNI 
    matches up or that the client presented a valid certificate.

    Best regards
    Tim Düsterhus

Reply via email to