On 24 Jun 13:29, Froehlich, Dominik wrote:
> Hi,
> 
> 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:
> 
> 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.
> 
> Consider this HAproxy config:
> 
> global
>   log /dev/log len 4096 format rfc3164 syslog info
> 
> defaults
>   log global
>   mode http
>   timeout connect 5s
>   timeout client 1h
>   timeout server 5s
> 
> frontend myfrontend
>   bind :443 ssl crt /etc/cert/server.pem crt-list /crt-list
>   log-format "%ci:%cp [%tr] (%ID) %ft %b/%s %TR/%Tw/%Tc/%Tr/%Tt %ST %B %CC 
> %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r %sslc %sslv"
> 
>   capture request header Host len 256
> 
>   http-request set-header X-SSL-Client              %[ssl_c_used]            
> if { ssl_c_used }
>   http-request set-header X-SSL-Client-Session-ID   %[ssl_fc_session_id,hex] 
> if { ssl_c_used }
>   http-request set-header X-SSL-Client-Verify       %[ssl_c_verify]          
> if { ssl_c_used }
>   http-request set-header X-SSL-Client-Subject-DN   %{+Q}[ssl_c_s_dn]        
> if { ssl_c_used }
>   http-request set-header X-SSL-Client-Subject-CN   %{+Q}[ssl_c_s_dn(cn)]    
> if { ssl_c_used }
>   http-request set-header X-SSL-Client-Issuer-DN    %{+Q}[ssl_c_i_dn]        
> if { ssl_c_used }
>   http-request set-header X-SSL-Client-NotBefore    %{+Q}[ssl_c_notbefore]   
> if { ssl_c_used }
>   http-request set-header X-SSL-Client-NotAfter     %{+Q}[ssl_c_notafter]    
> if { ssl_c_used }
> 
>   use_backend bob if { hdr(host) -m dom bob.com }
>   use_backend alice if { hdr(host) -m dom alice.com }

Thanks for taking the time to write this report.

SNI and host header are indeed different.

You should consider using req.ssl_sni instead of hdr(host).

Regards,

> 
>   default_backend alice
> 
> backend alice
>   server alice localhost:8080 check
> 
> backend bob
>   server bob localhost:8081 check
> 
> ---
> So this HAproxy hosts two domains alice.com and bob.com. It uses the 
> following crt-list to make TLS connections:
> 
> /etc/cert/server.pem [ca-file /alice.ca.pem verify required] *.alice.com
> /etc/cert/server.pem [ca-file /bob.ca.pem verify required] *.bob.com
> 
> ---
> So any client connecting to alice.com must present a certificate signed by 
> the Alice CA and any client connecting to bob.com must present a certificate 
> signed by the Bob CA.
> 
> 
> However, I noticed that HAproxy does allow me to “spoof” the host header to 
> bob.com even though I did a TLS handshake with alice.com. The request will be 
> forwarded to bob.com with the alice.com certificate:
> 
> curl -v -k --cert alice.com.crt --key alice.com.key --resolve 
> www.alice.com:9443:127.0.0.1<http://www.alice.com:9443:127.0.0.1> 
> https://www.alice.com:9443/headers -H "host: www.bob.com<http://www.bob.com>"
> 
> * Added www.alice.com:9443:127.0.0.1 to DNS cache
> * Hostname www.alice.com was found in DNS cache
> *   Trying 127.0.0.1...
> * TCP_NODELAY set
> * Connected to www.alice.com (127.0.0.1) port 9443 (#0)
> * ALPN, offering h2
> * ALPN, offering http/1.1
> * successfully set certificate verify locations:
> *   CAfile: /etc/ssl/cert.pem
>   CApath: none
> (…)
> > GET /headers HTTP/1.1
> > Host: www.bob.com
> > User-Agent: curl/7.64.1
> > Accept: */*
> >
> < HTTP/1.1 200 OK
> < date: Thu, 24 Jun 2021 13:07:17 GMT
> < content-length: 578
> < content-type: text/plain; charset=utf-8
> <
> Hello from Bob!
> 
> ----- Headers Received -----
> Accept : [*/*]
> User-Agent : [curl/7.64.1]
> X-Ssl-Client : [1]
> X-Ssl-Client-Issuer-Dn : 
> [/C=US/ST=California/L=AliceLand/O=Alice.com/CN=Alice.com Root 
> CA/[email protected]]
> X-Ssl-Client-Notafter : [220624125634Z]
> X-Ssl-Client-Notbefore : [210624125634Z]
> X-Ssl-Client-Session-Id : 
> [D941ECCAACAFEBC5CB3AE17794B54DC3DFC7549C401DB20D7EC5ADC48244D3D0]
> X-Ssl-Client-Subject-Cn : [Alice]
> X-Ssl-Client-Subject-Dn : 
> [/C=US/ST=Michigan/L=Detroit/O=Alice.com/CN=Alice/[email protected]]
> X-Ssl-Client-Verify : [0]
> 
> ---
> So basically anyone who can get a client certificate from Alice.com can use 
> it to also connect to Bob.com without getting validated against Bob’s CA.
> 
> I’ve tested this with HAproxy 2.2.14.
> 
> My questions:
> 
>   *   HAproxy does seem to treat SNI (L5) and HTTP Host Header (L7) as 
> unrelated. Is this true?
>   *   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?
>   *   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.
> 
> 
> Best regards,
> Dom

-- 
 (o-    Julien Pivotto
 //\    Open-Source Consultant
 V_/_   Inuits - https://www.inuits.eu

Attachment: signature.asc
Description: PGP signature

Reply via email to