Désactiver SSL en tant que protocole dans HttpsURLConnection
En raison de la CANICHE de la vulnérabilité, de mon serveur, hébergé dans Amazon AWS ne plus soutenir SSLv3.
En conséquence, la première connexion HTTPS mon application Android ne contre le serveur provoque une erreur lors de la connexion a été établie.
Error reading server response: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x77d8ab68: Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x7339ad74:0x00000000)
[....]
Caused by: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x77d8ab68: Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x7339ad74:0x00000000)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:448)
at com.android.okhttp.Connection.upgradeToTls(Connection.java:146)
at com.android.okhttp.Connection.connect(Connection.java:107)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294)
at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
L'erreur ne se produit que dans la première demande. Les demandes ultérieures de travail pour un certain temps.
Pour résoudre ce problème que je suis en train de supprimer SSL à partir de la liste des protocoles acceptés par le client Android, et s'assurer que je vais seulement avec le protocole TLS.
Pour ce faire, j'ai mis une coutume SSLSocketFactory qui supprime SSL à partir de la liste des protocoles activés et pris en charge monogramme suites.
/**
* SSLSocketFactory that wraps one existing SSLSocketFactory and delegetes into it adding
* a new cipher suite
*/
public class TLSOnlySocketFactory extends SSLSocketFactory {
private final SSLSocketFactory delegate;
public TLSOnlySocketFactory(SSLSocketFactory delegate) {
this.delegate = delegate;
}
@Override
public String[] getDefaultCipherSuites() {
return getPreferredDefaultCipherSuites(this.delegate);
}
@Override
public String[] getSupportedCipherSuites() {
return getPreferredSupportedCipherSuites(this.delegate);
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
final Socket socket = this.delegate.createSocket(s, host, port, autoClose);
((SSLSocket)socket).setEnabledCipherSuites(getPreferredDefaultCipherSuites(delegate));
((SSLSocket)socket).setEnabledProtocols(getEnabledProtocols((SSLSocket)socket));
return socket;
}
[.....]
((SSLSocket)socket).setEnabledCipherSuites(getPreferredDefaultCipherSuites(delegate));
((SSLSocket) socket).setEnabledProtocols(getEnabledProtocols((SSLSocket)socket));
return socket;
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
final Socket socket = this.delegate.createSocket(host, port);
((SSLSocket)socket).setEnabledCipherSuites(getPreferredDefaultCipherSuites(delegate));
((SSLSocket) socket).setEnabledProtocols(getEnabledProtocols((SSLSocket)socket));
return socket;
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
final Socket socket = this.delegate.createSocket(address, port, localAddress, localPort);
((SSLSocket)socket).setEnabledCipherSuites(getPreferredDefaultCipherSuites(delegate));
((SSLSocket) socket).setEnabledProtocols(getEnabledProtocols((SSLSocket)socket));
return socket;
}
private String[] getPreferredDefaultCipherSuites(SSLSocketFactory sslSocketFactory) {
return getCipherSuites(sslSocketFactory.getDefaultCipherSuites());
}
private String[] getPreferredSupportedCipherSuites(SSLSocketFactory sslSocketFactory) {
return getCipherSuites(sslSocketFactory.getSupportedCipherSuites());
}
private String[] getCipherSuites(String[] cipherSuites) {
final ArrayList<String> suitesList = new ArrayList<String>(Arrays.asList(cipherSuites));
final Iterator<String> iterator = suitesList.iterator();
while (iterator.hasNext()) {
final String cipherSuite = iterator.next();
if (cipherSuite.contains("SSL")) {
iterator.remove();
}
}
return suitesList.toArray(new String[suitesList.size()]);
}
private String[] getEnabledProtocols(SSLSocket socket) {
final ArrayList<String> protocolList = new ArrayList<String>(Arrays.asList(socket.getSupportedProtocols()));
final Iterator<String> iterator = protocolList.iterator();
while (iterator.hasNext()) {
final String protocl = iterator.next();
if (protocl.contains("SSL")) {
iterator.remove();
}
}
return protocolList.toArray(new String[protocolList.size()]);
}
}
Comme vous le voyez, mon SSLSocketFactory délégués dans un autre SSLSocketFactory et ce qu'il fait est tout simplement la suppression SSL à partir de la liste des protocoles activés.
- Je mettre en place cette usine
final TLSOnlySocketFactory tlsOnlySocketFactory = new TLSOnlySocketFactory(HttpsURLConnection.getDefaultSSLSocketFactory());
HttpsURLConnection.setDefaultSSLSocketFactory(tlsOnlySocketFactory);
Cela ne résout PAS le problème. De temps à autre, je vois toujours l'erreur lors de la connexion a été établie. Curieusement, cela ne veut pas le réparer, mais il est clair que de minimiser les occurrences de la question.
Comment pourrais-je la force de la HttpsUrlConnection dans mon client Android pour utiliser uniquement TLS?
Merci.
source d'informationauteur GaRRaPeTa
Vous devez vous connecter pour publier un commentaire.
J'ai pris @GaRRaPeTa de réponse et regroupés en un simple appel de méthode. Vous pouvez utiliser le NetCipher bibliothèque pour obtenir un moderne TLS config lors de l'utilisation d'Android
HttpsURLConnection
. NetCipher configure le " HttpsURLConnection exemple, d'utiliser les meilleures prises en charge TLS version, supprime SSLv3 de soutien, et configure la meilleure suite d'algorithmes pour que le protocole TLS version. Tout d'abord, l'ajouter à votre construire.gradle:Ou vous pouvez télécharger le netcipher-1.2.jar et de l'inclure directement dans votre application. Alors au lieu de l'appeler:
Appeler cela:
La solution ci-dessus(s) ne fonctionne pas pour moi, donc c'est ce que j'ai appris et fait pour surmonter ce problème.
Pour les appareils plus anciens, que Android 5.0, le fournisseur de sécurité par défaut eu ces propriétés:
Une solution qui a fonctionné pour moi ici, c'est de patcher le "Fournisseur" si nécessaire lors du démarrage de l'application, de sorte qu'il n'aura plus SSLv3 sur sa liste de protocoles.
Une façon simple de patch Android à partir de votre application est ceci: (compte tenu que vous avez accès à Google Play Store services.)
Prendre un coup d'oeil à: https://developer.android.com/training/articles/security-gms-provider.html?#patching pour plus d'info.
Côté de @GaRRaPeTa de la réponse, s'il vous plaît faites le makeSocketsafe méthode permet de déterminer si le support n'est pas encore convertis à NoSSLv3SSLSocket pour éviter Stackoverflow questions:
PS. Pas de commentaire alors que c'est sur un post séparé.
J'ai récemment testé cette aide SSLContext (que j'ai besoin d'accéder à Trustmanager) au lieu de mettre mon propre NoSSLv3Factory et jusqu'à présent je n'ai pas eu de problèmes.
Vous pouvez ensuite l'utiliser dans vos HttpsURLConnection objet:
Cela ne signifie pas que vous devez rester au top de TLS vulnérabilités du si et de modifier la spécifié de chiffrement si aucun protocole SSL/TLS vulnérabilités révélées publiquement.
Une liste des algorithmes de chiffrement et les fournisseurs que vous pouvez utiliser sont répertoriés ici
Le premier bloc de code, mineur le changement de clé pour ce scénario, a été principalement prises de cette SORTE de réponse
Aussi, vous devez savoir que vous pouvez forcer TLS v1.2 pour les appareils Android 4.0 qui n'ont pas activé par défaut:
Ce devrait être la première ligne de votre Demande: