You are viewing a plain text version of this content. The canonical link for it is here.
Posted to bugs@httpd.apache.org by bu...@apache.org on 2017/12/05 12:27:01 UTC

[Bug 61857] New: Security: Apache 2.4 not verifying URL hostname against certificate in SSL handshake for WebSockets

https://bz.apache.org/bugzilla/show_bug.cgi?id=61857

            Bug ID: 61857
           Summary: Security: Apache 2.4 not verifying URL hostname
                    against certificate in SSL handshake for WebSockets
           Product: Apache httpd-2
           Version: 2.4.10
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: major
          Priority: P2
         Component: mod_proxy_wstunnel
          Assignee: bugs@httpd.apache.org
          Reporter: markusgausling@googlemail.com
  Target Milestone: ---

Issue was found in Apache 2.4.10 and is still available in trunk. The Apache
2.4.10 is not verifying URL hostname against certificate in SSL handshake for
WebSockets even when SSLProxyCheckPeerCN and/or SSLProxyCheckPeerName are
enabled.

Configure Apache as a "WebSocket Relay" that allows local clients to connect to
(local) ​Apache using "ws://" and Apache then maps this to "wss://" and passes
the request on to the actual serving backend.

Define a Virtual Host for this:
    <VirtualHost 127.0.0.1:8888>
        SSLProxyEngine On
        ProxyRequests Off

        <Proxy "*">
            Order deny,allow
            Deny from all
            Allow from 127.0.0.1
        </Proxy>

        ProxyPass /websocket/ wss://mywebsocket.org/
    </VirtualHost>

A local request to Apache for ws://​127.0.0.1:8888/​websocket/would end up in a
request to wss://mywebsocket.org/.

Define the following security option (amongst others):
    SSLProxyCheckPeerCN on
    SSLProxyCheckPeerName on
    SSLProxyCheckPeerExpire on
    SSLProxyCACertificateFile "/opt/apache2/mycert.pem"
    SSLProxyVerify require
    SSLProxyVerifyDepth 1

While Apache properly checks if the server provided certificate is not expired
and also matches mycert.pem it does not validate the subject name or the
subject alternative names.

This is a security hole and means e.g. when mapping the IP address of
mywebsocket.org in /etc/hosts on Linux to e.g. to myotherwebsocket.org, then
Apache establishes a secure connection to mywebsocket.org however it does not
complain about the mismatch of the hostname in the request
("myotherwebsocket.org") vs. the one in the certificate provided during TLS
session establishment ("mywebsocket.org").

Doing a similar thing for HTTP (define Reverse Proxy which does http-to-https
mapping) works, i.e. Apache corectly refuses the connection as it realizes that
name in certificate provided by server and hostname in request URL do not
match.

========================================
Source of Apache 2.4.10 
-----------------------
The function ssl_io_filter_handshake() (in modules/ssl/ssl_engine_io.c) checks
the peer hostname or the URL (depending on the Apache configuration) against
the CN, agsinst the name or the subjectAltNames in the peer provided
certificate.
It does this only if hostname_note is not empty:
  const char *hostname_note = apr_table_get(c->notes,
                                            "proxy-request-hostname");


In proxy_http_handler() of module/proxy/mod_proxy_http.c the connection
establishment with the backend stores "proxy-request-hostname":

    /* Step Three: Create conn_rec */
    backconn = backend->connection;
    if (!backconn) {
        if ((status = ap_proxy_connection_create_ex(proxy_function,
                                                    backend, r)) != OK)
            break;
        backconn = backend->connection;

        /*
         * On SSL connections set a note on the connection what CN is
         * requested, such that mod_ssl can check if it is requested to do
         * so.
         */
        if (backend->ssl_hostname) {
            apr_table_setn(backend->connection->notes,
                           "proxy-request-hostname",
                           backend->ssl_hostname);
        }
    }

For the WebSocket tunneling in function proxy_wstunnel_handler() (in file:
modules/proxy/mod_proxy_wstunnel.c) adding "proxy-request-hostname" is missing
and as a result later in the TLS/SSL handshake the check is not done.

========================================

My proposed fix is to add the same code used in the HTTP case for the
WebSockets  in function proxy_wstunnel_handler() (file:
modules/proxy/mod_proxy_wstunnel.c) as well:

  /* Step Three: Create conn_rec */
  if (!backend->connection) {
      if ((status = ap_proxy_connection_create(scheme, backend,
                                               c, r->server)) != OK)
          break;

+      /*
+       * On SSL connections set a note on the connection what CN is
+       * requested, such that mod_ssl can check if it is requested to do
+       * so.
+       */
+       if (backend->ssl_hostname) {
+           apr_table_setn(backend->connection->notes,
+                          "proxy-request-hostname",
+                          backend->ssl_hostname);
      }
  }

This is 2.4.10 code but the code in trunk looks slightly different but the fix
should be similar.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: bugs-unsubscribe@httpd.apache.org
For additional commands, e-mail: bugs-help@httpd.apache.org


[Bug 61857] Security: Apache 2.4 not verifying URL hostname against certificate in SSL handshake for WebSockets

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=61857

--- Comment #3 from Yann Ylavic <yl...@gmail.com> ---
Backported to 2.4.x (>= 2.4.40) in r1859844.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: bugs-unsubscribe@httpd.apache.org
For additional commands, e-mail: bugs-help@httpd.apache.org


[Bug 61857] Security: Apache 2.4 not verifying URL hostname against certificate in SSL handshake for WebSockets

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=61857

--- Comment #1 from Yann Ylavic <yl...@gmail.com> ---
Thanks for the report and patch.

Committed in r1818726, such that SSLProxyCheckPeer* directives can be used for
any proxy module (with SSL backend connections).

Does that work for you?

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: bugs-unsubscribe@httpd.apache.org
For additional commands, e-mail: bugs-help@httpd.apache.org


[Bug 61857] Security: Apache 2.4 not verifying URL hostname against certificate in SSL handshake for WebSockets

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=61857

Markus Gausling <ma...@googlemail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |FIXED

--- Comment #2 from Markus Gausling <ma...@googlemail.com> ---
Yes looks good. 

Thanks
Markus

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: bugs-unsubscribe@httpd.apache.org
For additional commands, e-mail: bugs-help@httpd.apache.org