Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ca md too weak #682

Closed
nirdothan-zz opened this issue May 2, 2020 · 23 comments · Fixed by #685
Closed

ca md too weak #682

nirdothan-zz opened this issue May 2, 2020 · 23 comments · Fixed by #685
Labels

Comments

@nirdothan-zz
Copy link

Trying to connect with user cert and failing with the following error message:
SSL_CTX_use_certificate_file: error:140AB18E:SSL routines:SSL_CTX_use_certificate:ca md too weak
If I understand correctly, the rejection is coming from openssl, and the option is either to configure openssl with tls-cipher=DEFAULT:@SECLEVEL=0 or to rebuild the certificate. I'm not sure how to do either one.
The certificate that I am using is originally a p12 file from which I've extracted the cert and key in PEM format.
running in ubuntu 20.04 LTS - 64-bit

@DimitriPapadopoulos
Copy link
Collaborator

DimitriPapadopoulos commented May 2, 2020

See #673

You may be trying to connect to an obsolete FortiGate appliance This appliance seems to depend on weak algorithms that have been removed (by default or irremediably?) from the OpenSSL libraries bundled with Ubuntu 20.04. Have you tried the --insecure-ssl, --min-tls and --seclevel-1 options?

By the way, is this PKCS #12 certificate a personal certificate you need to authenticate with the VPN appliance?

Would you happen to have some information on the model of FortiGate device and the version of FortiOS? If FortiOS is not too ancient you might find the information in the XML-formatted configuration sent by the FortiGate appliance and output by openfortivpn -v -v. It would help if you could show us the (sanitized) piece of information.

@DimitriPapadopoulos
Copy link
Collaborator

Also please provide more information on the certificate (sanitize before posting):

openssl x509 -text -in <certificate_file.pem>
openssl x509 -nokeys -info -in <keystore.p12>

@nirdothan-zz
Copy link
Author

Thanks @DimitriPapadopoulos
An obsolete FortiGate appliance on the other end is quite possible.
I'll try to find out version information from IT, hopefully by tomorrow.

--insecure-ssl, --min-tls and --seclevel-1 didn't help

Here's the cert info that you asked for. Please let me know if I've sanitized it too far.

sanitized output of openssl x509 -text -in <certificate_file.pem>

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 4283 (0x10bb)
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: REDACTED
        Validity
            Not Before: Jul 27 11:42:04 2017 GMT
            Not After : Jul 27 11:42:04 2037 GMT
        Subject: REDACTED
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    REDACTED
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            X509v3 Key Usage: 
                Digital Signature, Non Repudiation, Key Encipherment
    Signature Algorithm: sha1WithRSAEncryption
 
            REDACTED

-----BEGIN CERTIFICATE-----
   REDACTED
-----END CERTIFICATE-----

sanitized output of openssl pkcs12 -nokeys -info -in <keystore.p12>

Bag Attributes
    friendlyName: nird
    localKeyID: 6E REDACTED A3
subject=C =  REDACTED

issuer=C = REDACTED

-----BEGIN CERTIFICATE-----
REDACTED
-----END CERTIFICATE-----
Bag Attributes: <No Attributes>
subject= REDCATED

issuer=C = REDACTED

-----BEGIN CERTIFICATE-----
REDACTED
-----END CERTIFICATE-----

@DimitriPapadopoulos
Copy link
Collaborator

DimitriPapadopoulos commented May 2, 2020

I don't use certificates to authenticate myself so I cannot tell for sure, but SHA-1 is known to be weak and obsolete. Also I have a client certificate as a first level of authentication for IPSec connections and it's based on SHA-256, not SHA-1. Perhaps that's the problem here.

Are you comfortable with compiling your own version of openfortivpn? You may try to replace @SECLEVEL=1 with @SECLEVEL=0 in the following lines and run openfortivpn --insecure-ssl --seclevel-1 again:

cipher_list = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4@SECLEVEL=1";

const char *cipher_list = "DEFAULT@SECLEVEL=1";

@DimitriPapadopoulos
Copy link
Collaborator

Also you may want to run nmap --script ssl-enum-ciphers against you VPN appliance and post here the (saniitized) output to have a look at supported ciphers. For example:

$ nmap --script ssl-enum-ciphers -p 443 www.fortinet.com
Starting Nmap 7.80 ( https://nmap.org ) at 2020-05-02 00:00 UTC
Nmap scan report for www.fortinet.com (13.56.33.144)
Host is up (0.17s latency).
rDNS record for 13.56.33.144: ec2-13-56-33-144.us-west-1.compute.amazonaws.com

PORT    STATE SERVICE
443/tcp open  https
| ssl-enum-ciphers: 
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_256_CCM_8 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_256_CCM (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 (secp256r1) - A
|       TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_128_CCM_8 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_128_CCM (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 (secp256r1) - A
|       TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 (secp256r1) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 (secp256r1) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 2048) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 2048) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CCM_8 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CCM (rsa 2048) - A
|       TLS_RSA_WITH_ARIA_256_GCM_SHA384 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CCM_8 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CCM (rsa 2048) - A
|       TLS_RSA_WITH_ARIA_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: server
|_  least strength: A

Nmap done: 1 IP address (1 host up) scanned in 34.80 seconds
$ 

@nirdothan-zz
Copy link
Author

here's the code change:

diff --git a/src/tunnel.c b/src/tunnel.c
index 4a3da5e..0e20bb2 100644
--- a/src/tunnel.c
+++ b/src/tunnel.c
@@ -966,7 +966,7 @@ int ssl_connect(struct tunnel *tunnel)
                        const char *cipher_list;
 
                        if (tunnel->config->seclevel_1)
-                               cipher_list = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4@SECLEVEL=1";
+                               cipher_list = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4@SECLEVEL=0";
                        else
                                cipher_list = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4";
                        tunnel->config->cipher_list = strdup(cipher_list);
@@ -977,7 +977,7 @@ int ssl_connect(struct tunnel *tunnel)
                        tunnel->config->min_tls = TLS1_VERSION;
 #endif
                if (!tunnel->config->cipher_list && tunnel->config->seclevel_1) {
-                       const char *cipher_list = "DEFAULT@SECLEVEL=1";
+                       const char *cipher_list = "DEFAULT@SECLEVEL=0";
 
                        tunnel->config->cipher_list = strdup(cipher_list);
                }

This is the execution

sudo /usr/local/bin/openfortivpn -u nird --min-tls 1.0 --insecure-ssl --seclevel-1 --user-cert=***.crt.pem --user-key=***key.pem host:port -v

DEBUG:  openfortivpn 1.13.3
DEBUG:  revision v1.13.3+git43.g77ec854
WARN:   Could not load config file "/etc/openfortivpn/config" (No such file or directory).
VPN account password: 
DEBUG:  Config host = "***"
DEBUG:  Config realm = ""
DEBUG:  Config port = "***"
DEBUG:  Config username = "***"
DEBUG:  Resolving gateway host ip
DEBUG:  Establishing ssl connection
DEBUG:  server_addr: ***
DEBUG:  server_port: ***
DEBUG:  gateway_addr: ***
DEBUG:  gateway_port: ***
ERROR:  SSL_CTX_use_certificate_file: error:140AB18E:SSL routines:SSL_CTX_use_certificate:ca md too weak
INFO:   Closed connection to gateway.
DEBUG:  server_addr: ***
DEBUG:  server_port: ***
DEBUG:  gateway_addr: ***
DEBUG:  gateway_port: ***
ERROR:  SSL_CTX_use_certificate_file: error:140AB18E:SSL routines:SSL_CTX_use_certificate:ca md too weak
INFO:   Could not log out.
PORT    STATE SERVICE
***/tcp open  https
| ssl-enum-ciphers: 
|   TLSv1.1: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 2048) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 2048) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
|       TLS_DHE_RSA_WITH_SEED_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C
|       TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (dh 2048) - C
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|     compressors: 
|       NULL
|     cipher preference: server
|     warnings: 
|      REDACTED
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_256_CCM_8 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_256_CCM (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 (secp256r1) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 2048) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CCM_8 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CCM (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_128_CCM_8 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_128_CCM (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 (secp256r1) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 2048) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CCM_8 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CCM (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
|       TLS_DHE_RSA_WITH_SEED_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C
|       TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (dh 2048) - C
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|     compressors: 
|       NULL
|     cipher preference: server
|     warnings: 
|     REDACTED
|_  least strength: C

@DimitriPapadopoulos
Copy link
Collaborator

DimitriPapadopoulos commented May 2, 2020

The SSL_CTX_set_security_level man page shows that level 2 (the default on Ubuntu 20.04 as far as I can tell) should be sufficient to support the ciphers used by your FortiGate appliance. Perhaps you don't have the very latest version of FortiOS, but the cipher list is clearly more recent/secure than one one of the VPN appliances I connect to routinely:

$ Starting Nmap 7.80 ( https://nmap.org ) at 2020-05-02 00:00 UTC
Nmap scan report for xxxxxxxxxxxxx.xxx.xx (xxx.xxx.xxx.xxx)
Host is up (0.027s latency).
rDNS record for xxx.xxx.xxx.xxx: xxxxxxx.xxxxx.xxx.xx

PORT    STATE SERVICE
443/tcp open  https
| ssl-enum-ciphers: 
|   TLSv1.0: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 2048) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 2048) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
|       TLS_DHE_RSA_WITH_SEED_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C
|       TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (dh 2048) - C
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|     compressors: 
|       NULL
|     cipher preference: server
|     warnings: 
|       64-bit block cipher 3DES vulnerable to SWEET32 attack
|   TLSv1.1: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 2048) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 2048) - A 
|       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
|       TLS_DHE_RSA_WITH_SEED_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C
|       TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (dh 2048) - C
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|     compressors: 
|       NULL
|     cipher preference: server
|     warnings: 
|       64-bit block cipher 3DES vulnerable to SWEET32 attack
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_256_CCM_8 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_256_CCM (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 (secp256r1) - A
|       TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 (secp256r1) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 2048) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CCM_8 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CCM (rsa 2048) - A
|       TLS_RSA_WITH_ARIA_256_GCM_SHA384 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_128_CCM_8 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_128_CCM (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 (secp256r1) - A
|       TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 (secp256r1) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 2048) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CCM_8 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CCM (rsa 2048) - A
|       TLS_RSA_WITH_ARIA_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
|       TLS_DHE_RSA_WITH_SEED_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C
|       TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (dh 2048) - C
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|     compressors: 
|       NULL
|     cipher preference: server
|     warnings: 
|       64-bit block cipher 3DES vulnerable to SWEET32 attack
|_  least strength: C

Nmap done: 1 IP address (1 host up) scanned in 7.92 seconds
$ 

I don't know yet how to get OpenSSL to accept SHA-1 certificates. Will keep looking.

@DimitriPapadopoulos
Copy link
Collaborator

See for example:

As far as I can understand @SECLEVEL=1 should be enough to support your sha1WithRSAEncryption certificate. Not sure why --seclevel-1 does not help at this point.

@DimitriPapadopoulos
Copy link
Collaborator

DimitriPapadopoulos commented May 2, 2020

I think certificates are checked here:

if (!SSL_CTX_use_PrivateKey_file(

before security level is set according to --seclevel-1:

openfortivpn/src/tunnel.c

Lines 964 to 984 in 77ec854

if (!tunnel->config->insecure_ssl) {
if (!tunnel->config->cipher_list) {
const char *cipher_list;
if (tunnel->config->seclevel_1)
cipher_list = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4@SECLEVEL=1";
else
cipher_list = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4";
tunnel->config->cipher_list = strdup(cipher_list);
}
} else {
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
if (tunnel->config->min_tls <= 0)
tunnel->config->min_tls = TLS1_VERSION;
#endif
if (!tunnel->config->cipher_list && tunnel->config->seclevel_1) {
const char *cipher_list = "DEFAULT@SECLEVEL=1";
tunnel->config->cipher_list = strdup(cipher_list);
}
}

I believe we need to move the whole part of the code that handles --insecure-ssl, --seclevel-1, --min-tls and calls SSL_set_cipher_list() before messing with certificates.

@nirdothan-zz
Copy link
Author

I tried moving things around. No luck yet

@DimitriPapadopoulos
Copy link
Collaborator

DimitriPapadopoulos commented May 3, 2020

In any case what did change in Debian 10 and Ubuntu 20.04 is the default security level moving from @SECLEVEL=1 to @SECLEVEL=2:

$ openssl version -a
OpenSSL 1.1.1f  31 Mar 2020
built on: Mon Apr 20 11:53:50 2020 UTC
platform: debian-amd64
options:  bn(64,64) rc4(16x,int) des(int) blowfish(ptr) 
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -Wa,--noexecstack -g -O2 -fdebug-prefix-map=/build/openssl-P_ODHM/openssl-1.1.1f=. -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_TLS_SECURITY_LEVEL=2 -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DNDEBUG -Wdate-time -D_FORTIFY_SOURCE=2
OPENSSLDIR: "/usr/lib/ssl"
ENGINESDIR: "/usr/lib/x86_64-linux-gnu/engines-1.1"
Seeding source: os-specific
$ 

Note the -DOPENSSL_TLS_SECURITY_LEVEL=2 OpenSSL compilation option.

This is documented to cause this kind of interoperability issues in the SSL_CTX_set_security_level man page:

WARNING at this time setting the security level higher than 1 for general internet use is likely to cause considerable interoperability issues and is not recommended. This is because the SHA1 algorithm is very widely used in certificates and will be rejected at levels higher than 1 because it only offers 80 bits of security.

The default security level can be configured when OpenSSL is compiled by setting -DOPENSSL_TLS_SECURITY_LEVEL=level. If not set then 1 is used.

I am confident this is the problem at hand but I am also confident that this can be fixed programmatically from within openfortivpn because this is only a default setting. We just need to find a way to get back to @SECLEVEL=1 for certificates.

@DimitriPapadopoulos
Copy link
Collaborator

@nirdothan What have you been trying so far? I don't have a personal certificate to test myself but I believe PR #685 should work for you. Can you give it a try?

@nirdothan-zz
Copy link
Author

with PR #685 I still get the same error:

DEBUG:  openfortivpn 1.13.3
DEBUG:  revision v1.6.0+git277.g32bd42a
DEBUG:  Loaded config file "/etc/openfortivpn/config".
DEBUG:  Loaded password from config file "/etc/openfortivpn/config"
DEBUG:  Config host = ***
DEBUG:  Config realm = ""
DEBUG:  Config port = "***"
DEBUG:  Config username = "***"
DEBUG:  Resolving gateway host ip
DEBUG:  Establishing ssl connection
DEBUG:  server_addr: ***
DEBUG:  server_port: ***
DEBUG:  gateway_addr: ***
DEBUG:  gateway_port: ***
DEBUG:  Setting cipher list to: HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4
ERROR:  SSL_CTX_use_certificate_file: error:140AB18E:SSL routines:SSL_CTX_use_certificate:ca md too weak
INFO:   Closed connection to gateway.
DEBUG:  server_addr: ***
DEBUG:  server_port: ***
DEBUG:  gateway_addr: ***
DEBUG:  gateway_port: ***
DEBUG:  Setting cipher list to: HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4
ERROR:  SSL_CTX_use_certificate_file: error:140AB18E:SSL routines:SSL_CTX_use_certificate:ca md too weak
INFO:   Could not log out.

playing with cipher list still yields the same issue:

DEBUG:  Setting cipher list to: HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4@SECLEVEL=1
DEBUG:  Setting min proto version to: 0x301
ERROR:  SSL_CTX_use_certificate_file: error:140AB18E:SSL routines:SSL_CTX_use_certificate:ca md too weak

@DimitriPapadopoulos
Copy link
Collaborator

DimitriPapadopoulos commented May 3, 2020

You still need --seclevel-1 and perhaps --min-tls=1.2.

By the way, does it work for you on Ubuntu 18.04?

@DimitriPapadopoulos
Copy link
Collaborator

Also adding the following to /etc/ssl/openssl.cnf seems to be working on Debian 10, although it's an ugly workaround:

[system_default_sect]
CipherString = DEFAULT@SECLEVEL=1

Does it help on Ubuntu 20.04?

@nirdothan-zz
Copy link
Author

sorry, none of those seem to make a difference. I don't have Ubuntu 18.04 handy

@nirdothan-zz
Copy link
Author

IT generated a new SHA-256 signed cert bundle for me and I am now able to connect.
Thanks a lot @DimitriPapadopoulos for your help

@DimitriPapadopoulos
Copy link
Collaborator

DimitriPapadopoulos commented May 4, 2020

I would have loved to fix that in openfortivpn. I should be possible to set @SECLEVEL=1 for certificates since it works for communication with the FortiGate appliance (see #673).

I guess the only way to investigate would be to generate an SHA-1 certificate and attempt to connect myself to a test FortiGate.

@DimitriPapadopoulos
Copy link
Collaborator

DimitriPapadopoulos commented May 4, 2020

Apart from the order, I think the problem is that we call SSL_set_cipher_list():

tunnel->ssl_context = SSL_CTX_new(SSLv23_client_method());
[...]
tunnel->ssl_handle = SSL_new(tunnel->ssl_context);
[...]
SSL_set_cipher_list(tunnel->ssl_handle, ...

and this will apply only to the tunnel->ssl_handle connection, not to certificates.

Instead we should call SSL_CTX_set_cipher_list():

tunnel->ssl_context = SSL_CTX_new(SSLv23_client_method());
[...]
SSL_CTX_set_cipher_list(tunnel->ssl_context, ...

@nirdothan-zz
Copy link
Author

nirdothan-zz commented May 4, 2020 via email

@DimitriPapadopoulos
Copy link
Collaborator

@nirdothan I have updated the existing PR #685. Would you be willing to test it?

@nirdothan-zz
Copy link
Author

@DimitriPapadopoulos I think that your fix works, unfortunately I could not connect, as I suspect that they revoked my old cert.
With the new cert, it connects fine, so as far as regression goes, your PR didn't break anything.

DEBUG:  openfortivpn 1.13.3
DEBUG:  revision v1.6.0+git278.gfe46c2c
DEBUG:  Loaded config file "config-cert".
DEBUG:  Loaded password from config file "config-cert"
DEBUG:  Config host = ***
DEBUG:  Config realm = ""
DEBUG:  Config port = "***"
DEBUG:  Config username = "***"
DEBUG:  Resolving gateway host ip
DEBUG:  Establishing ssl connection
DEBUG:  server_addr: ***
DEBUG:  server_port: ***
DEBUG:  gateway_addr: ***
DEBUG:  gateway_port: ***
DEBUG:  Setting cipher list to: DEFAULT@SECLEVEL=1
DEBUG:  Setting min proto version to: 0x301
DEBUG:  Gateway certificate validation failed.
DEBUG:  Gateway certificate digest found in white list.
INFO:   Connected to gateway.
DEBUG:  Error reading from SSL connection (Protocol violation with EOF).
DEBUG:  server_addr: ***
DEBUG:  server_port: ***
DEBUG:  gateway_addr: ***
DEBUG:  gateway_port: ***
DEBUG:  Setting cipher list to: DEFAULT@SECLEVEL=1
DEBUG:  Setting min proto version to: 0x301
DEBUG:  Gateway certificate validation failed.
DEBUG:  Gateway certificate digest found in white list.
DEBUG:  Error reading from SSL connection (Protocol violation with EOF).
DEBUG:  Error issuing /remote/logincheck request
ERROR:  Could not authenticate to gateway. Please check the password, client certificate, etc.
DEBUG:  SSL error -4
INFO:   Closed connection to gateway.
DEBUG:  server_addr: ***
DEBUG:  server_port: ***
DEBUG:  gateway_addr: ***
DEBUG:  gateway_port: ***
DEBUG:  Setting cipher list to: DEFAULT@SECLEVEL=1
DEBUG:  Setting min proto version to: 0x301
DEBUG:  Gateway certificate validation failed.
DEBUG:  Gateway certificate digest found in white list.
INFO:   Logged out.

@DimitriPapadopoulos
Copy link
Collaborator

@nirdothan Thank you for checking, it really helps. Yes, I agree with you, I suspect the FortiGate closes the SSL connection as soon as it finds the certificate has been revoked. This change does get you further and I believe it would have worked all the way had the SHA-1 certificate not been revoked.

This change makes total sense, does not seem to break other use cases, and does help in your case (up to some point at least). I think it's good for merging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants