nextcloud / android

đŸ“± Nextcloud Android app
https://play.google.com/store/apps/details?id=com.nextcloud.client
GNU General Public License v2.0
4.27k stars 1.77k forks source link

Falied SSL Initialization #714

Closed leleobhz closed 7 years ago

leleobhz commented 7 years ago

Actual behaviour

Expected behaviour

Steps to reproduce

  1. Configure server with Let's encrypt with secp384r1 as pubkey algorithm
  2. Configure nginx as following ssl options:
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;
  1. Check the Android app.

Environment data

Android version: 7.0

Device model: Asus ZenFone3 - Beta Tester

Stock or customized system: Official Asus Beta Tester

Nextcloud app version: Latest Nightly and Latest Play Store

Nextcloud server version: 11.0.2 Stable

Logs

adb logcat | grep GetRemoteStatusOperation

03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation: Connection check at https://<server>: SSL exception
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation: javax.net.ssl.SSLHandshakeException: Handshake failed
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:429)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at com.owncloud.android.lib.common.network.AdvancedSslSocketFactory.verifyPeerIdentity(AdvancedSslSocketFactory.java:248)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at com.owncloud.android.lib.common.network.AdvancedSslSocketFactory.createSocket(AdvancedSslSocketFactory.java:185)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:707)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpConnectionAdapter.open(MultiThreadedHttpConnectionManager.java:1361)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:387)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at com.owncloud.android.lib.common.OwnCloudClient.executeMethod(OwnCloudClient.java:222)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at com.owncloud.android.lib.common.OwnCloudClient.executeMethod(OwnCloudClient.java:192)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at com.owncloud.android.lib.resources.status.GetRemoteStatusOperation.tryConnection(GetRemoteStatusOperation.java:87)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at com.owncloud.android.lib.resources.status.GetRemoteStatusOperation.run(GetRemoteStatusOperation.java:192)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at com.owncloud.android.lib.common.operations.RemoteOperation.execute(RemoteOperation.java:136)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at com.owncloud.android.operations.GetServerInfoOperation.run(GetServerInfoOperation.java:81)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at com.owncloud.android.lib.common.operations.RemoteOperation.execute(RemoteOperation.java:136)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at com.owncloud.android.services.OperationsService$ServiceHandler.nextOperation(OperationsService.java:482)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at com.owncloud.android.services.OperationsService$ServiceHandler.handleMessage(OperationsService.java:418)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at android.os.Handler.dispatchMessage(Handler.java:102)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at android.os.Looper.loop(Looper.java:159)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at android.os.HandlerThread.run(HandlerThread.java:61)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation: Caused by: javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0x7f666fd340: Failure in SSL library, usually a protocol error
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation: error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE (external/boringssl/src/ssl/s3_pkt.c:610 0x7f666189e0:0x00000001)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation: error:1000009a:SSL routines:OPENSSL_internal:HANDSHAKE_FAILURE_ON_CLIENT_HELLO (external/boringssl/src/ssl/s3_clnt.c:764 0x7f76ceaf76:0x00000000)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
03-03 17:51:18.861  6198  6238 E GetRemoteStatusOperation:  ... 20 more

testssl.sh on server

[leonardo@pruuu testssl.sh]$ ./testssl.sh --wide https://<FQDN> 

###########################################################
    testssl.sh       2.9dev from https://testssl.sh/dev/
    (27aa257 2017-02-28 15:42:28 -- )

      This program is free software. Distribution and
             modification under GPLv2 permitted.
      USAGE w/o ANY WARRANTY. USE IT AT YOUR OWN RISK!

       Please file bugs @ https://testssl.sh/bugs/

###########################################################

 Using "OpenSSL 1.0.2-chacha (1.0.2i-dev)" [~183 ciphers]
 on pruuu:$PWD/bin/openssl.Linux.x86_64
 (built: "Jun 22 19:32:29 2016", platform: "linux-x86_64")

 Start 2017-03-03 18:04:33    -->> 192.168.196.20:443 (<FQDN>) <<--

 rDNS (192.168.196.20):  -- 
 Service detected:       HTTP

 Testing protocols via sockets except SPDY+HTTP2 

 SSLv2      not offered (OK)
 SSLv3      not offered (OK)
 TLS 1      not offered
 TLS 1.1    not offered
 TLS 1.2    offered (OK)
 SPDY/NPN   h2, http/1.1 (advertised)
 HTTP2/ALPN h2, http/1.1 (offered)

 Testing ~standard cipher lists 

 Null Ciphers                 not offered (OK)
 Anonymous NULL Ciphers       not offered (OK)
 Anonymous DH Ciphers         not offered (OK)
 40 Bit encryption            not offered (OK)
 56 Bit export ciphers        not offered (OK)
 Export Ciphers (general)     not offered (OK)
 Low (<=64 Bit)               not offered (OK)
 DES Ciphers                  not offered (OK)
 "Medium" grade encryption    not offered (OK)
 Triple DES Ciphers           not offered (OK)
 High grade encryption        offered (OK)

 Testing robust (perfect) forward secrecy, (P)FS -- omitting Null Authentication/Encryption, 3DES, RC4 

 PFS is offered (OK), ciphers follow (client/browser support is important here) 

Hexcode  Cipher Suite Name (OpenSSL)       KeyExch.   Encryption  Bits     Cipher Suite Name (RFC)
-----------------------------------------------------------------------------------------------------------------------------
 xc02c   ECDHE-ECDSA-AES256-GCM-SHA384     ECDH 256   AESGCM      256      TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384            
 xc02b   ECDHE-ECDSA-AES128-GCM-SHA256     ECDH 256   AESGCM      128      TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256            

 Elliptic curves offered:     prime256v1 secp384r1 secp521r1 brainpoolP384r1 brainpoolP512r1 

 Testing server preferences 

 Has server cipher order?     yes (OK)
 Negotiated protocol          TLSv1.2
 Negotiated cipher            ECDHE-ECDSA-AES256-GCM-SHA384, 256 bit ECDH (P-256)
 Cipher order
    TLSv1.2:   ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES128-GCM-SHA256 
    h2:        ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES128-GCM-SHA256 
    http/1.1:  ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES128-GCM-SHA256 

 Testing server defaults (Server Hello) 

 TLS extensions (standard)    "renegotiation info/#65281" "EC point formats/#11" "heartbeat/#15" "server name/#0" 
                              "next protocol/#13172" "application layer protocol negotiation/#16" 
 Session Tickets RFC 5077     (none)
 SSL Session ID support       yes
 TLS clock skew               random values, no fingerprinting possible 
 Signature Algorithm          SHA256 with RSA
 Server key size              ECDSA 384 bits
 Fingerprint / Serial         SHA1 E7B2175F930130C627396DECAC6CEED607A1BBFC / 035991A57F1159615464ACA8A03128487999
                              SHA256 AF546B253736AA91E29B366E557FE0C777EF5688A2004E3B6B8E53C29360529F
 Common Name (CN)             <FQDN>
 subjectAltName (SAN)         <FQDN> 
 Issuer                       Let's Encrypt Authority X3 (Let's Encrypt from US)
 Trust (hostname)             Ok via SAN and CN (works w/o SNI)
 Chain of trust               Ok   
 EV cert (experimental)       no 
 Certificate Expiration       89 >= 30 days (2017-03-03 15:54 --> 2017-06-01 15:54 -0300)
 # of certificates provided   2
 Certificate Revocation List  --
 OCSP URI                     http://ocsp.int-x3.letsencrypt.org/
 OCSP must staple             No
 OCSP stapling                --
 DNS CAA RR (experimental)    --

 Testing HTTP header response @ "/" 

 HTTP Status Code             302 Found, redirecting to "https://<FQDN>/login"
 HTTP clock skew              0 sec from localtime
 Strict Transport Security    182 days=15768000 s, includeSubDomains, preload
 Public Key Pinning           --
 Server banner                nginx/1.11.10
 Application banner           --
 Cookie(s)                    1 issued: 3/1 secure, 4/1 HttpOnly -- maybe better try target URL of 30x
 Security headers             X-Frame-Options SAMEORIGIN
                              X-XSS-Protection 1; mode=block
                              X-Content-Type-Options nosniff
                              Content-Security-Policy; media-src *; connect-src *
 Reverse Proxy banner         --

 Testing vulnerabilities 

 Heartbleed (CVE-2014-0160)                not vulnerable (OK)
 CCS (CVE-2014-0224)                       not vulnerable (OK)
 Secure Renegotiation (CVE-2009-3555)      not vulnerable (OK)
 Secure Client-Initiated Renegotiation     not vulnerable (OK)
 CRIME, TLS (CVE-2012-4929)                not vulnerable (OK)
 BREACH (CVE-2013-3587)                    no HTTP compression (OK)  - only supplied "/" tested
 POODLE, SSL (CVE-2014-3566)               not vulnerable (OK)
 TLS_FALLBACK_SCSV (RFC 7507)              No fallback possible, TLS 1.2 is the only protocol (OK)
 SWEET32 (CVE-2016-2183, CVE-2016-6329)    not vulnerable (OK)
 FREAK (CVE-2015-0204)                     not vulnerable (OK)
 DROWN (CVE-2016-0800, CVE-2016-0703)      not vulnerable on this port (OK)
                                           no RSA certificate, thus certificate can't be used with SSLv2 elsewhere
 LOGJAM (CVE-2015-4000), experimental      not vulnerable (OK): no DH EXPORT ciphers, no DH key detected

 BEAST (CVE-2011-3389)                     no SSL3 or TLS1 (OK)
 LUCKY13 (CVE-2013-0169)                   not vulnerable (OK)

 RC4 (CVE-2013-2566, CVE-2015-2808)        no RC4 ciphers detected (OK)

 Testing 359 ciphers via OpenSSL plus sockets against the server, ordered by encryption strength 

Hexcode  Cipher Suite Name (OpenSSL)       KeyExch.   Encryption  Bits     Cipher Suite Name (RFC)
-----------------------------------------------------------------------------------------------------------------------------
 xc02c   ECDHE-ECDSA-AES256-GCM-SHA384     ECDH 256   AESGCM      256      TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384            
 xc02b   ECDHE-ECDSA-AES128-GCM-SHA256     ECDH 256   AESGCM      128      TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256            

 Running browser simulations via sockets (experimental) 

 Android 2.3.7                 No connection
 Android 4.0.4                 No connection
 Android 4.1.1                 No connection
 Android 4.2.2                 No connection
 Android 4.3                   No connection
 Android 4.4.2                 TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384, 256 bit ECDH (P-256)
 Android 5.0.0                 TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256, 256 bit ECDH (P-256)
 Baidu Jan 2015                No connection
 BingPreview Jan 2015          TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384, 256 bit ECDH (P-256)
 Chrome 47 / OSX               TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256, 256 bit ECDH (P-256)
 Firefox 31.3.0ESR / Win7      TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256, 256 bit ECDH (P-256)
 Firefox 42 OS X               TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256, 256 bit ECDH (P-256)
 GoogleBot Feb 2015            TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256, 256 bit ECDH (P-256)
 IE 6 XP                       No connection
 IE 7 Vista                    No connection
 IE 8 XP                       No connection
 IE 8-10 Win 7                 No connection
 IE 11 Win 7                   TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384, 256 bit ECDH (P-256)
 IE 11 Win 8.1                 TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384, 256 bit ECDH (P-256)
 IE 10 Win Phone 8.0           No connection
 IE 11 Win Phone 8.1           TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384, 256 bit ECDH (P-256)
 IE 11 Win Phone 8.1 Update    TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384, 256 bit ECDH (P-256)
 IE 11 Win 10                  TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384, 256 bit ECDH (P-256)
 Edge 13 Win 10                TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384, 256 bit ECDH (P-256)
 Edge 13 Win Phone 10          TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384, 256 bit ECDH (P-256)
 Java 6u45                     No connection
 Java 7u25                     No connection
 Java 8u31                     TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256, 256 bit ECDH (P-256)
 OpenSSL 0.9.8y                No connection
 OpenSSL 1.0.1l                TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384, 256 bit ECDH (P-256)
 OpenSSL 1.0.2e                TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384, 256 bit ECDH (P-256)
 Safari 5.1.9 OS X 10.6.8      No connection
 Safari 6 iOS 6.0.1            No connection
 Safari 6.0.4 OS X 10.8.4      No connection
 Safari 7 iOS 7.1              No connection
 Safari 7 OS X 10.9            No connection
 Safari 8 iOS 8.4              No connection
 Safari 8 OS X 10.10           No connection
 Safari 9 iOS 9                TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384, 256 bit ECDH (P-256)
 Safari 9 OS X 10.11           TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384, 256 bit ECDH (P-256)
 Apple ATS 9 iOS 9             TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384, 256 bit ECDH (P-256)

 Done 2017-03-03 18:05:40    -->> 192.168.196.20:443 (<FQDN>) <<--

[leonardo@pruuu testssl.sh]$ 
leleobhz commented 7 years ago

A comment: From Chrome in the same phone, It works well.

AndyScherzinger commented 7 years ago

@oparoz is this a cipher used, not being supported by default?

leleobhz commented 7 years ago

Curiously from a StartSSL cert it works, so I suspect something related to eliptic curve I choose for letsencrypt, but its weird to me. Remembering StartSSL certificates got revoked by Mozilla, Apple and Google since mid 2016, so I want to change it to lets encrypt, but want a tighter security.

Wonderfall commented 7 years ago

I'm also using LE P-384 certificates and these ssl parameters and I've no problem. But I had the same issue as yours on a previous CyanogenMod build, perhaps you can to try to upgrade your ROM?

leleobhz commented 7 years ago

@Wonderfall I'm using Android 7.0 from ZenFone3. I'm their beta tester and my phone is original and with warranty. I'll report this issue to Asus but I still wondering why Google Canary works and nextcloud app does not :/

I'll test you nginx config too.

Wonderfall commented 7 years ago

Like I said, I had the same problem. It worked with Firefox, Chrome, but not with any app. I'm not an expert but maybe (likely) Chrome has its own embedded toolkit implementing SSL/TLS.

The best you can do is to report to Asus since I'm sure it's ROM-related.

leleobhz commented 7 years ago

The best you can do is to report to Asus since I'm sure it's ROM-related.

But if its ROM issue, Why Chrome Canary works well here, accepting the certificate? Also, in Dev options, Webview implementation, both Chrome Canary and WebView did not worked within the app.

That said, Im also suspecting a ROM issue, but I ask in this bug report to something like "What Nextcloud App can do to allow the access?"

Wonderfall commented 7 years ago

But if its ROM issue, Why Chrome Canary works well here, accepting the certificate?

I don't know, there must be something with the SSL/TLS implementation. It's working for me since a very specific build of CyanogenMod 14 (I'm now using LineageOS). During some time, it didn't work but it was indeed working while I was on CyanogenMod 13. If @AndyScherzinger remembers, we discussed briefly that matter on Twitter.

I don't say I'm 100% sure, but it's more than likely that this issue comes from your ROM. I think Asus itself has something to do allow the access, but like I said I can't be totally sure.

leleobhz commented 7 years ago

Hello Devs!

I read http://stackoverflow.com/questions/39133437/sslhandshakeexception-handshake-failed-on-android-n-7-0 today and tested here to see what happens.

Ive changed my systemd unit from

ExecStart=/srv/dehydrated/dehydrated -a secp384r1 -o /etc/ssl/nginx -f /srv/leonardoamaral.com.br.conf -d %i -t dns-01 -k '/srv/dehydrated/hooks/cloudflare/hook.py' -c

to

ExecStart=/srv/dehydrated/dehydrated -a prime256v1 -o /etc/ssl/nginx -f /srv/leonardoamaral.com.br.conf -d %i -t dns-01 -k '/srv/dehydrated/hooks/cloudflare/hook.py' -c

And forced the rekeying with -x, regenerating the pubkey and fullchain again. Also in ssl_ecdh_curve I've leaved the default instead forcing the option "ssl_ecdh_curve secp521r1 secp384r1" and it worked.

So I think its related to eliptic curves and not by the system itself. What bothers me is why Chrome Canary works even with a secp384r1 key and the app does not.

Anyways, Asus got a post on their beta forum and I'm waiting for a answer.

Thanks for all posts and help!

EDIT: Just the way Letsencrypt key got generated manifests the issue. With

ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_ecdh_curve 'brainpoolP512r1:secp521r1:brainpoolP384r1:secp384r1:prime256v1';

Worked if I use prime256v1 as public key algorithm in Let's Encrypt key generator, but secp384r1 did not worked. Any combination with pubkey of type secp384r1 also does not work, so I think this is the precise issue.

Wonderfall commented 7 years ago

It's related to the elliptic curve used by the certs, but I think the fact it works on Chrome Canary and not in the app shows exactly that the system is in fault. Let us know what Asus will answer.

As a "temporary fix" you can use multiple certificates at the same time with nginx.

tobiasKaminsky commented 7 years ago

So, unfortunately we cannot do anything here, if I hopefully understood it correctly, therefore closing it. (please feel free to re-open if I am wrong)

Wonderfall commented 7 years ago

From what I've seen, this issue is specific to Android 7.0. Is has been resolved in Android 7.1.