Comment désactiver SSLv3 dans Android pour HttpsUrlConnection?

Nous avons écrit une application client dans Android qui se connecte avec des serveurs https en utilisant HttpsUrlConnection apis. En raison de la vulnérabilité de Poodle, nous devons désactiver SSLv3 de la liste des protocoles activés tout en invoquant toute demande.

Nous avons suivi les lignes directrices prises par Oracle comme http://www.oracle.com/technetwork/java/javase/documentation/cve-2014-3566-2342133.html

  • Création d'un dessin vide dans Android
  • MapActivity ne peut pas être résolu à un type
  • Vendeurs d'Appcelerator MonoTouch - Quel est le meilleur pour un développeur .NET?
  • Pourquoi utiliser Fragments?
  • Android illégalstateception
  • Afficher le mode après l'installation ou la mise à jour de l'application
  • Et ajouté la ligne suivante avant d'appeler la connexion url

    java.lang.System.setProperty("https.protocols", "TLSv1"); 

    Cette solution fonctionne bien avec le programme java normal. Nous avons obtenu SSLHandShakeException lorsqu'on tente de se connecter à un serveur qui ne fonctionne que sur le protocole SSLv3.

    Mais la préoccupation est : la même solution ne fonctionne pas pour Android. Est-ce que je manque quelque chose ou dois-je essayer une autre approche pour Android? Veuillez suggérer.

  • Application de numérotation Android
  • Android Studio gradle ne compile pas la version spécifiée
  • Chaîne fractionnée avec. (Dot) personnage java android
  • Modification de l'icône du menu Overflow Android par programme
  • Quel type de pitfals existe pour la signature Android APK?
  • Activité de démarrage d'Android depuis le service
  • 8 Solutions collect form web for “Comment désactiver SSLv3 dans Android pour HttpsUrlConnection?”

    J'ai trouvé la solution pour cela en analysant les paquets de données en utilisant wireshark. Ce que j'ai trouvé, c'est que tout en établissant une connexion sécurisée, l'Android remontait à SSLv3 à partir de TLSv1 . C'est un bug dans les versions Android <4.4, et il peut être résolu en supprimant le protocole SSLv3 de la liste des protocoles activés. J'ai créé une classe customFactory personnalisée appelée NoSSLv3SocketFactory.java. Utilisez-le pour créer une fiche socketfactory.

     /*Copyright 2015 Bhavit Singh Sengar Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.*/ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; import java.net.SocketAddress; import java.net.SocketException; import java.nio.channels.SocketChannel; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.net.ssl.HandshakeCompletedListener; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; public class NoSSLv3SocketFactory extends SSLSocketFactory{ private final SSLSocketFactory delegate; public NoSSLv3SocketFactory() { this.delegate = HttpsURLConnection.getDefaultSSLSocketFactory(); } public NoSSLv3SocketFactory(SSLSocketFactory delegate) { this.delegate = delegate; } @Override public String[] getDefaultCipherSuites() { return delegate.getDefaultCipherSuites(); } @Override public String[] getSupportedCipherSuites() { return delegate.getSupportedCipherSuites(); } private Socket makeSocketSafe(Socket socket) { if (socket instanceof SSLSocket) { socket = new NoSSLv3SSLSocket((SSLSocket) socket); } return socket; } @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { return makeSocketSafe(delegate.createSocket(s, host, port, autoClose)); } @Override public Socket createSocket(String host, int port) throws IOException { return makeSocketSafe(delegate.createSocket(host, port)); } @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { return makeSocketSafe(delegate.createSocket(host, port, localHost, localPort)); } @Override public Socket createSocket(InetAddress host, int port) throws IOException { return makeSocketSafe(delegate.createSocket(host, port)); } @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { return makeSocketSafe(delegate.createSocket(address, port, localAddress, localPort)); } private class NoSSLv3SSLSocket extends DelegateSSLSocket { private NoSSLv3SSLSocket(SSLSocket delegate) { super(delegate); } @Override public void setEnabledProtocols(String[] protocols) { if (protocols != null && protocols.length == 1 && "SSLv3".equals(protocols[0])) { List<String> enabledProtocols = new ArrayList<String>(Arrays.asList(delegate.getEnabledProtocols())); if (enabledProtocols.size() > 1) { enabledProtocols.remove("SSLv3"); System.out.println("Removed SSLv3 from enabled protocols"); } else { System.out.println("SSL stuck with protocol available for " + String.valueOf(enabledProtocols)); } protocols = enabledProtocols.toArray(new String[enabledProtocols.size()]); } super.setEnabledProtocols(protocols); } } public class DelegateSSLSocket extends SSLSocket { protected final SSLSocket delegate; DelegateSSLSocket(SSLSocket delegate) { this.delegate = delegate; } @Override public String[] getSupportedCipherSuites() { return delegate.getSupportedCipherSuites(); } @Override public String[] getEnabledCipherSuites() { return delegate.getEnabledCipherSuites(); } @Override public void setEnabledCipherSuites(String[] suites) { delegate.setEnabledCipherSuites(suites); } @Override public String[] getSupportedProtocols() { return delegate.getSupportedProtocols(); } @Override public String[] getEnabledProtocols() { return delegate.getEnabledProtocols(); } @Override public void setEnabledProtocols(String[] protocols) { delegate.setEnabledProtocols(protocols); } @Override public SSLSession getSession() { return delegate.getSession(); } @Override public void addHandshakeCompletedListener(HandshakeCompletedListener listener) { delegate.addHandshakeCompletedListener(listener); } @Override public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) { delegate.removeHandshakeCompletedListener(listener); } @Override public void startHandshake() throws IOException { delegate.startHandshake(); } @Override public void setUseClientMode(boolean mode) { delegate.setUseClientMode(mode); } @Override public boolean getUseClientMode() { return delegate.getUseClientMode(); } @Override public void setNeedClientAuth(boolean need) { delegate.setNeedClientAuth(need); } @Override public void setWantClientAuth(boolean want) { delegate.setWantClientAuth(want); } @Override public boolean getNeedClientAuth() { return delegate.getNeedClientAuth(); } @Override public boolean getWantClientAuth() { return delegate.getWantClientAuth(); } @Override public void setEnableSessionCreation(boolean flag) { delegate.setEnableSessionCreation(flag); } @Override public boolean getEnableSessionCreation() { return delegate.getEnableSessionCreation(); } @Override public void bind(SocketAddress localAddr) throws IOException { delegate.bind(localAddr); } @Override public synchronized void close() throws IOException { delegate.close(); } @Override public void connect(SocketAddress remoteAddr) throws IOException { delegate.connect(remoteAddr); } @Override public void connect(SocketAddress remoteAddr, int timeout) throws IOException { delegate.connect(remoteAddr, timeout); } @Override public SocketChannel getChannel() { return delegate.getChannel(); } @Override public InetAddress getInetAddress() { return delegate.getInetAddress(); } @Override public InputStream getInputStream() throws IOException { return delegate.getInputStream(); } @Override public boolean getKeepAlive() throws SocketException { return delegate.getKeepAlive(); } @Override public InetAddress getLocalAddress() { return delegate.getLocalAddress(); } @Override public int getLocalPort() { return delegate.getLocalPort(); } @Override public SocketAddress getLocalSocketAddress() { return delegate.getLocalSocketAddress(); } @Override public boolean getOOBInline() throws SocketException { return delegate.getOOBInline(); } @Override public OutputStream getOutputStream() throws IOException { return delegate.getOutputStream(); } @Override public int getPort() { return delegate.getPort(); } @Override public synchronized int getReceiveBufferSize() throws SocketException { return delegate.getReceiveBufferSize(); } @Override public SocketAddress getRemoteSocketAddress() { return delegate.getRemoteSocketAddress(); } @Override public boolean getReuseAddress() throws SocketException { return delegate.getReuseAddress(); } @Override public synchronized int getSendBufferSize() throws SocketException { return delegate.getSendBufferSize(); } @Override public int getSoLinger() throws SocketException { return delegate.getSoLinger(); } @Override public synchronized int getSoTimeout() throws SocketException { return delegate.getSoTimeout(); } @Override public boolean getTcpNoDelay() throws SocketException { return delegate.getTcpNoDelay(); } @Override public int getTrafficClass() throws SocketException { return delegate.getTrafficClass(); } @Override public boolean isBound() { return delegate.isBound(); } @Override public boolean isClosed() { return delegate.isClosed(); } @Override public boolean isConnected() { return delegate.isConnected(); } @Override public boolean isInputShutdown() { return delegate.isInputShutdown(); } @Override public boolean isOutputShutdown() { return delegate.isOutputShutdown(); } @Override public void sendUrgentData(int value) throws IOException { delegate.sendUrgentData(value); } @Override public void setKeepAlive(boolean keepAlive) throws SocketException { delegate.setKeepAlive(keepAlive); } @Override public void setOOBInline(boolean oobinline) throws SocketException { delegate.setOOBInline(oobinline); } @Override public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) { delegate.setPerformancePreferences(connectionTime, latency, bandwidth); } @Override public synchronized void setReceiveBufferSize(int size) throws SocketException { delegate.setReceiveBufferSize(size); } @Override public void setReuseAddress(boolean reuse) throws SocketException { delegate.setReuseAddress(reuse); } @Override public synchronized void setSendBufferSize(int size) throws SocketException { delegate.setSendBufferSize(size); } @Override public void setSoLinger(boolean on, int timeout) throws SocketException { delegate.setSoLinger(on, timeout); } @Override public synchronized void setSoTimeout(int timeout) throws SocketException { delegate.setSoTimeout(timeout); } @Override public void setTcpNoDelay(boolean on) throws SocketException { delegate.setTcpNoDelay(on); } @Override public void setTrafficClass(int value) throws SocketException { delegate.setTrafficClass(value); } @Override public void shutdownInput() throws IOException { delegate.shutdownInput(); } @Override public void shutdownOutput() throws IOException { delegate.shutdownOutput(); } @Override public String toString() { return delegate.toString(); } @Override public boolean equals(Object o) { return delegate.equals(o); } } } 

    Utilisez cette classe comme ceci lors de la connexion:

     SSLContext sslcontext = SSLContext.getInstance("TLSv1"); sslcontext.init(null, null, null); SSLSocketFactory NoSSLv3Factory = new NoSSLv3SocketFactory(sslcontext.getSocketFactory()); HttpsURLConnection.setDefaultSSLSocketFactory(NoSSLv3Factory); l_connection = (HttpsURLConnection) l_url.openConnection(); l_connection.connect(); 

    Inspiré par la réponse de Bhavit S. Sengar, il a regroupé cette technique dans un appel à méthode simple et décisive. Vous pouvez utiliser la bibliothèque NetCipher pour obtenir une configuration TLS moderne lors de l'utilisation de l'application HttpsURLConnection d'Android. NetCipher configure l'instance HttpsURLConnection pour utiliser la version TLS la plus prise en charge, supprime le support SSLv3 et configure la meilleure suite de chiffres pour cette version TLS. Tout d'abord, ajoutez-le à votre build.gradle :

     compile 'info.guardianproject.netcipher:netcipher:1.2' 

    Ou vous pouvez télécharger netcipher-1.2.jar et l'inclure directement dans votre application. Ensuite, au lieu d'appeler:

     HttpURLConnection connection = (HttpURLConnection) sourceUrl.openConnection(); 

    Appelez ceci:

     HttpsURLConnection connection = NetCipher.getHttpsURLConnection(sourceUrl); 

    Au début, j'ai essayé la réponse de Bhavit S. Sengar et cela a fonctionné pour la plupart des cas. Mais parfois, là où des problèmes, même lorsque le protocole SSLv3 a été supprimé des Protocoles activés sur un périphérique Android 4.4.4. Ainsi, la bibliothèque NetCipher de Hans-Christoph Steiner est parfaite pour résoudre ce problème autant que je pourrais le tester.

    Nous utilisons jsoup pour créer un tas de scrap web sur différents serveurs, de sorte que nous ne pouvons pas définir HttpsURLConnection connection = NetCipher.getHttpsURLConnection(sourceUrl); . Je suppose que c'est le même problème si vous utilisez OkHttp.

    La meilleure solution à laquelle nous sommes venus est de définir l' info.guardianproject.netcipher.client.TlsOnlySocketFactory partir de NetCipher comme DefaultSSLSocketFactory dans un bloc statique. Donc, il est défini pour l'ensemble de l'exécution de notre application:

     SSLContext sslcontext = SSLContext.getInstance("TLSv1"); sslcontext.init(null, null, null); SSLSocketFactory noSSLv3Factory = new TlsOnlySocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultSSLSocketFactory(noSSLv3Factory); 

    Si vous souhaitez inspecter les détails complets (avec trustAllCertificates ), vous pouvez le faire ici .

    Utilisez cet extrait de code, si le serveur est SSLv3 activé, il va échouer.

      SocketFactory sf = SSLSocketFactory.getDefault(); SSLSocket socket = (SSLSocket) sf.createSocket("host-name", 443); socket.setEnabledProtocols(new String[] { "TLSv1"}); socket.startHandshake(); 

    Se connecte avec le serveur https. Nous avons besoin d'un certificat en mode handshaking du côté client. Il y a 1 an, j'ai résolu un problème similaire en utilisant le certificat de signature automatique de la manière suivante:

     import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.X509Certificate; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; public class HttpsTrustManager implements X509TrustManager { private static TrustManager[] trustManagers; private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{}; @Override public void checkClientTrusted( java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException { } @Override public void checkServerTrusted( java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException { } public boolean isClientTrusted(X509Certificate[] chain) { return true; } public boolean isServerTrusted(X509Certificate[] chain) { return true; } @Override public X509Certificate[] getAcceptedIssuers() { return _AcceptedIssuers; } public static void allowAllSSL() { HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String arg0, SSLSession arg1) { return true; } }); SSLContext context = null; if (trustManagers == null) { trustManagers = new TrustManager[]{new HttpsTrustManager()}; } try { context = SSLContext.getInstance("TLS"); context.init(null, trustManagers, new SecureRandom()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } HttpsURLConnection.setDefaultSSLSocketFactory(context .getSocketFactory()); } } 

    Utilisation du client avant HttpsUrlConnection

     HttpsTrustManager.allowAllSSL(); 

    J'espère qu'il fonctionnera 🙂

      SSLContext sslContext = SSLContext.getInstance("TLSv1"); sslContext.init(null, null, null); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); httpURLConnection.setSSLSocketFactory(socketFactory); 

    HttpsURLConnection à l'aide de TSL crée une sécurité, l'implémentation d'Android retombera à SSLV3 en connexion.

    Veuillez consulter ce http://code.google.com/p/android/issues/detail?id=78431

    À l' aide de bibliothèques de clients d'éditeur PlayService s'exécutant sur Android, j'ai eu le même problème lors de l'exécution de l' exemple .

    L'a corrigé avec @ bhavit-s-sengar's awnser ci-dessus. Il fallait également modifier AndroidPublisherHelper.newTrustedTransport() à ceci:

     SSLContext sslcontext = SSLContext.getInstance("TLSv1"); sslcontext.init(null, null, null); // NoSSLv3SocketFactory is @bhavit-s-sengar's http://stackoverflow.com/a/29946540/8524 SSLSocketFactory noSSLv3Factory = new NoSSLv3SocketFactory(sslcontext.getSocketFactory()); NetHttpTransport.Builder netTransportBuilder = new NetHttpTransport.Builder(); netTransportBuilder.setSslSocketFactory(noSSLv3Factory); HTTP_TRANSPORT = netTransportBuilder.build(); 

    En fait, nous n'avons pas besoin de désactiver SSLV3 ou TLSV1.0, ce que nous avons besoin d'activer TLSV1.1 ou TLSv1.2 dans les périphériques Android <5.

    Le problème est que TLSv1.1 et TLSv1.2 ne sont pas activés sur Android <5 par défaut et pour se connecter en utilisant ce dernier protocole sécurisé, nous devons avoir à activer dans Android <5 périphériques.

    Cette solution a résolu mon problème: https://stackoverflow.com/a/45853669/3448003

    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.