Using possibly vulnerable cipher suites with SNI ================================================== CVE-2013-4508 [1] was assigned to this bug. History --------- * 2013-11-28: Fixed regression reported in [4]. Added note regarding dynamic client verification. Description ------------- A typical SNI configuration like: $HTTP["Host"] == "example.com" { ssl.pemfile = "/etc/ssl/certs/example.com.pem" } $SERVER["socket"] == ":443" { ssl.engine = "enable" ssl.pemfile = "/etc/ssl/certs/default.pem" ssl.cipher-list = "HIGH" } is vulnerable. It will use ssl.cipher-list = "DEFAULT" for "example.com", which contains vulnerable cipher suites. The bug was reported by Nathan Bishop . Detailed analysis ------------------- The code constructed from each config block that sets ssl.pemfile a SSL_CTX with the options from this block (options from parent blocks are NOT used). In SNI context it uses the SSL_CTX from the block that sets ssl.pemfile. The patch loads the private key and certificate from ssl.pemfile into separate variables, and also stores the names from ssl.ca-file for use with ssl.verifyclient. Each SSL_CTX also gets loaded with all values for ssl.ca-file from all blocks in the config. So the following options are working in SNI context: * ssl.pemfile * ssl.verifyclient.* (ssl.verifyclient.enforce of limited use) * ssl.ca-file: * build chains from all "merged" ssl.ca-file * use the "active" ssl.ca-file option to verify clients The following options are only working when binding SSL sockets: * ssl.engine * ssl.cipher-list * ssl.honor-cipher-order * ssl.empty-fragments * ssl.use-sslv2 * ssl.use-sslv3 * ssl.dh-file * ssl.ec-curve The following SSL options are independent from SNI: * ssl.disable-client-renegotiation * ssl.verifyclient.username * ssl.verifyclient.exportcert As the SNI context isn't checked to match the hostname, a user can still circumvent a SNI depending ssl.verifyclient.enforce by using a different SNI name than what the Host: header contains. Also openssl doesn't verify again on session resumption, so a user could establish a session without verification, and then connect to a "protected" SNI host. In order to dynamically verify clients ssl.verifyclient.username or ssl.verifyclient.exportcert must be used to export the verification result and somehow be checked. Additional notes ------------------ lighttpd doesn't set a cipher string by default; it will use the openssl default, which is usually something like "ALL:!aNULL:!eNULL" and very weak. Patching a different default string (like "HIGH:!aNULL") into lighttpd is easy (search for `SSL_CTX_set_cipher_list` in `network.c`), but this really should be fixed in openssl. Affected versions ------------------- All versions from 1.4.24 (first version supporting SNI) up to and including 1.4.33. Patch ------- See http://download.lighttpd.net/lighttpd/security/lighttpd-1.4.33_fix_ssl_sni.patch Fixed in ---------- 1.4.x: http://redmine.lighttpd.net/projects/lighttpd/repository/revisions/2913 1.4.34: not released yet (http://www.lighttpd.net/) Solutions or workaround ------------------------- Set all ssl options in each block that sets ssl.pemfile: $HTTP["Host"] == "example.com" { ssl.pemfile = "/etc/ssl/certs/example.com.pem" ssl.cipher-list = "HIGH" } $SERVER["socket"] == ":443" { ssl.engine = "enable" ssl.pemfile = "/etc/ssl/certs/default.pem" ssl.cipher-list = "HIGH" } References ------------ [1] http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-4508 [2] http://redmine.lighttpd.net/issues/2525 [3] http://redmine.lighttpd.net/projects/lighttpd/repository/revisions/2913/diff/ GPG signatures ---------------- * http://download.lighttpd.net/lighttpd/security/lighttpd-1.4.33_fix_ssl_sni.patch.asc * http://download.lighttpd.net/lighttpd/security/lighttpd_sa_2013_01.txt.asc