Opened 4 years ago

Closed 3 years ago

#2035 closed defect (fixed)

Can't get old SSL cert to work - ca md too weak

Reported by: jez9999@… Owned by:
Priority: minor Milestone:
Component: nginx-core Version: 1.19.x
Keywords: ssl Cc: jez9999@…
uname -a: Linux vm-debian-main 4.19.0-8-amd64 #1 SMP Debian 4.19.98-1 (2020-01-26) x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.14.2
built with OpenSSL 1.1.1c 28 May 2019 (running with OpenSSL 1.1.1d 10 Sep 2019)
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-tBUzFN/nginx-1.14.2=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --with-mail=dynamic --with-mail_ssl_module --add-dynamic-module=/build/nginx-tBUzFN/nginx-1.14.2/debian/modules/http-auth-pam --add-dynamic-module=/build/nginx-tBUzFN/nginx-1.14.2/debian/modules/http-dav-ext --add-dynamic-module=/build/nginx-tBUzFN/nginx-1.14.2/debian/modules/http-echo --add-dynamic-module=/build/nginx-tBUzFN/nginx-1.14.2/debian/modules/http-upstream-fair --add-dynamic-module=/build/nginx-tBUzFN/nginx-1.14.2/debian/modules/http-subs-filter

Description

I'm trying to use an old SSL cert for one of my sites, and nginx fails to start with the error:

nginx: [emerg] SSL_CTX_add0_chain_cert("/etc/ssl/certs/game-point.net_crt_withcabundle.pem") failed (SSL: error:1415A18E:SSL routines:ssl_cert_add0_chain_cert:ca md too weak)
nginx: configuration file /etc/nginx/nginx.conf test failed

I do NOT wish to generate a newer certificate - I'm aware of the security issues with using old certs. I want to get this one to work despite it's being old and insecure. Don't ask me why. :-)

However, I can't get past this error. I tried changing ssl_ciphers in my /snippets/ssl.conf file:

ssl_ciphers ALL:@SECLEVEL=0;

But I still get the same error when Nginx starts. Is there some built-in setting that prevents security level getting set to 0 or something?

Change History (3)

comment:1 by Maxim Dounin, 3 years ago

SSL ciphers are configured by nginx after loading the certificates, so changing security level via the cipher string does not affect certificate loading and does not prevent the error in question.

To resolve this, appropriate OpenSSL config can be used to set the desired security level before the certificates are loaded by nginx, for example:

openssl_conf = default_conf

[default_conf]
ssl_conf = ssl_sect

[ssl_sect]
system_default = system_default_sect

[system_default_sect]
CipherString = DEFAULT:@SECLEVEL=0

(If needed, instead of changing the system default OpenSSL configuration file it is possible to provide nginx-specific one via the OPENSSL_CONF environment variable.)

It is also possible to reorder nginx code to set ciphers before loading certificates, so the @SECLEVEL=... hack would apply to loading server certificates when used in ssl_ciphers. Not sure it worth the effort though, as this is probably the only question about using weak server certificates I've seen. On the other hand, the change is rather trivial and can be also beneficial with upcoming security level changes in OpenSSL 3.0.

Patch below, testing is appreciated:

# HG changeset patch
# User Maxim Dounin <mdounin@mdounin.ru>
# Date 1628909078 -10800
#      Sat Aug 14 05:44:38 2021 +0300
# Node ID e7e32750c4e4904bc7c9a2bf3c9fa3c98d76a35d
# Parent  dda421871bc213dd2eb3da0015d6228839323583
SSL: ciphers now set before loading certificates (ticket #2035).

To load old/weak server or client certificates it might be needed to adjust
the security level, as introduced in OpenSSL 1.1.0.  This change ensures that
ciphers are set before loading the certificates, so security level changes
via the cipher string apply to certificate loading.

diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c
--- a/src/http/modules/ngx_http_grpc_module.c
+++ b/src/http/modules/ngx_http_grpc_module.c
@@ -4896,6 +4896,12 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ng
     cln->handler = ngx_ssl_cleanup_ctx;
     cln->data = glcf->upstream.ssl;
 
+    if (ngx_ssl_ciphers(cf, glcf->upstream.ssl, &glcf->ssl_ciphers, 0)
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
     if (glcf->upstream.ssl_certificate) {
 
         if (glcf->upstream.ssl_certificate_key == NULL) {
@@ -4927,12 +4933,6 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ng
         }
     }
 
-    if (ngx_ssl_ciphers(cf, glcf->upstream.ssl, &glcf->ssl_ciphers, 0)
-        != NGX_OK)
-    {
-        return NGX_ERROR;
-    }
-
     if (glcf->upstream.ssl_verify) {
         if (glcf->ssl_trusted_certificate.len == 0) {
             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -4944,6 +4944,12 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, n
     cln->handler = ngx_ssl_cleanup_ctx;
     cln->data = plcf->upstream.ssl;
 
+    if (ngx_ssl_ciphers(cf, plcf->upstream.ssl, &plcf->ssl_ciphers, 0)
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
     if (plcf->upstream.ssl_certificate) {
 
         if (plcf->upstream.ssl_certificate_key == NULL) {
@@ -4975,12 +4981,6 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, n
         }
     }
 
-    if (ngx_ssl_ciphers(cf, plcf->upstream.ssl, &plcf->ssl_ciphers, 0)
-        != NGX_OK)
-    {
-        return NGX_ERROR;
-    }
-
     if (plcf->upstream.ssl_verify) {
         if (plcf->ssl_trusted_certificate.len == 0) {
             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -797,6 +797,13 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *
                                           ngx_http_ssl_npn_advertised, NULL);
 #endif
 
+    if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
+                        conf->prefer_server_ciphers)
+        != NGX_OK)
+    {
+        return NGX_CONF_ERROR;
+    }
+
     if (ngx_http_ssl_compile_certificates(cf, conf) != NGX_OK) {
         return NGX_CONF_ERROR;
     }
@@ -829,13 +836,6 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *
         }
     }
 
-    if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
-                        conf->prefer_server_ciphers)
-        != NGX_OK)
-    {
-        return NGX_CONF_ERROR;
-    }
-
     conf->ssl.buffer_size = conf->buffer_size;
 
     if (conf->verify) {
diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -2432,6 +2432,12 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, n
     cln->handler = ngx_ssl_cleanup_ctx;
     cln->data = uwcf->upstream.ssl;
 
+    if (ngx_ssl_ciphers(cf, uwcf->upstream.ssl, &uwcf->ssl_ciphers, 0)
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
     if (uwcf->upstream.ssl_certificate) {
 
         if (uwcf->upstream.ssl_certificate_key == NULL) {
@@ -2463,12 +2469,6 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, n
         }
     }
 
-    if (ngx_ssl_ciphers(cf, uwcf->upstream.ssl, &uwcf->ssl_ciphers, 0)
-        != NGX_OK)
-    {
-        return NGX_ERROR;
-    }
-
     if (uwcf->upstream.ssl_verify) {
         if (uwcf->ssl_trusted_certificate.len == 0) {
             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c
--- a/src/mail/ngx_mail_ssl_module.c
+++ b/src/mail/ngx_mail_ssl_module.c
@@ -394,6 +394,13 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, 
     cln->handler = ngx_ssl_cleanup_ctx;
     cln->data = &conf->ssl;
 
+    if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
+                        conf->prefer_server_ciphers)
+        != NGX_OK)
+    {
+        return NGX_CONF_ERROR;
+    }
+
     if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
                              conf->certificate_keys, conf->passwords)
         != NGX_OK)
@@ -430,13 +437,6 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, 
         }
     }
 
-    if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
-                        conf->prefer_server_ciphers)
-        != NGX_OK)
-    {
-        return NGX_CONF_ERROR;
-    }
-
     if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
         return NGX_CONF_ERROR;
     }
diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c
--- a/src/stream/ngx_stream_proxy_module.c
+++ b/src/stream/ngx_stream_proxy_module.c
@@ -2185,6 +2185,10 @@ ngx_stream_proxy_set_ssl(ngx_conf_t *cf,
     cln->handler = ngx_ssl_cleanup_ctx;
     cln->data = pscf->ssl;
 
+    if (ngx_ssl_ciphers(cf, pscf->ssl, &pscf->ssl_ciphers, 0) != NGX_OK) {
+        return NGX_ERROR;
+    }
+
     if (pscf->ssl_certificate) {
 
         if (pscf->ssl_certificate_key == NULL) {
@@ -2216,10 +2220,6 @@ ngx_stream_proxy_set_ssl(ngx_conf_t *cf,
         }
     }
 
-    if (ngx_ssl_ciphers(cf, pscf->ssl, &pscf->ssl_ciphers, 0) != NGX_OK) {
-        return NGX_ERROR;
-    }
-
     if (pscf->ssl_verify) {
         if (pscf->ssl_trusted_certificate.len == 0) {
             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c
--- a/src/stream/ngx_stream_ssl_module.c
+++ b/src/stream/ngx_stream_ssl_module.c
@@ -720,6 +720,13 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf
                                            ngx_stream_ssl_servername);
 #endif
 
+    if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
+                        conf->prefer_server_ciphers)
+        != NGX_OK)
+    {
+        return NGX_CONF_ERROR;
+    }
+
     if (ngx_stream_ssl_compile_certificates(cf, conf) != NGX_OK) {
         return NGX_CONF_ERROR;
     }
@@ -752,13 +759,6 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf
         }
     }
 
-    if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
-                        conf->prefer_server_ciphers)
-        != NGX_OK)
-    {
-        return NGX_CONF_ERROR;
-    }
-
     if (conf->verify) {
 
         if (conf->client_certificate.len == 0 && conf->verify != 3) {

comment:2 by Maxim Dounin <mdounin@…>, 3 years ago

In 7904:419c066cb710/nginx:

SSL: ciphers now set before loading certificates (ticket #2035).

To load old/weak server or client certificates it might be needed to adjust
the security level, as introduced in OpenSSL 1.1.0. This change ensures that
ciphers are set before loading the certificates, so security level changes
via the cipher string apply to certificate loading.

comment:3 by Maxim Dounin, 3 years ago

Resolution: fixed
Status: newclosed

Fix committed, thanks for reporting this.

Note: See TracTickets for help on using tickets.