Включение SSLv2Hello вызывает сбой подтверждения SSL для конечных точек AWS

Мы размещаем на AWS, и все наши конечные точки используют предопределенные политики безопасности, которые не допускают TLS ниже 1,2 (то есть TLS-1-2-2017-01 для ELB или TLSv1.2_2018 для CloudFront).

Один из наших клиентов пожаловался на то, что подключение к нашей конечной точке из клиента Java завершается ошибкой SSLHandshakeException , и подтвердил, что TLSv1.2 был включен в клиенте.

Дальнейшее расследование показало, что на клиенте также был включен SSLv2Hello по устаревшим причинам. Его отключение решило проблему, однако я до сих пор не совсем понимаю, почему это вообще проблема.

Эксперименты показывают, что проблема касается только конечных точек AWS - я пробовал различные веб-сайты, размещенные на AWS через ELB и Cloudfront , и получил эту ошибку. Сайты, размещенные на AWS, но использующие другие решения SSL (например, LetsEncrypt), не имеют этой проблемы, и у них нет веб-сайтов, размещенных где-либо еще.

Вот простой фрагмент Java, который я использовал для экспериментов:

import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;

public class TestConnect {

    public static void main(String[] args) {
      String url="https://alertlogic.com"; // hosted on AWS behind ELB - failure
//      String url="https://myx.ostankin.net"; // hosted on AWS, but using LetsEncrypt - ok
//      String url="https://google.com"; // Not hosted on AWS - ok
        System.setProperty("https.protocols", "TLSv1.2,SSLv2Hello");
//        System.setProperty("https.protocols", "TLSv1.2");
      try {
        URL restURL = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) restURL.openConnection();
        conn.setRequestMethod("GET");
        int responseCode = conn.getResponseCode();
        String responseMessage = conn.getResponseMessage();
        System.out.println("Response:");
        System.out.println(responseMessage);
      } catch(Exception e) {
        e.printStackTrace();
      }
    }
}

При запуске в данном конфигурации, это не удается со следующим исключением:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.http.HttpURLConnection.followRedirect0(HttpURLConnection.java:2701)
    at sun.net.www.protocol.http.HttpURLConnection.followRedirect(HttpURLConnection.java:2623)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1806)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1474)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
    at TestConnect.main(TestConnect.java:17)

Запуск с -Djavax.net.debug = ssl: handshake обеспечивает довольно длинный вывод, но если я вырезал все элементы инициализации, все закончилось следующим образом:

main, READ: TLSv1.2 Handshake, length = 333
*** ECDH ServerKeyExchange
Signature Algorithm SHA1withRSA
Server key: Sun EC public key, 256 bits
  public x coord: 21436757520046799441414055942148383722667165679440737888092161490006597177581
  public y coord: 15404188333633930557065698234035214201299701177286160881126576519412706199661
  parameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)
main, READ: TLSv1.2 Handshake, length = 4
*** ServerHelloDone
*** ECDHClientKeyExchange
ECDH Public value:  { 4, 244, 123, 66, 147, 148, 50, 164, 198, 11, 116, 147, 132, 129, 249, 46, 144, 69, 1, 121, 111, 104, 31, 233, 10, 114, 250, 76, 140, 98, 224, 1, 117, 35, 0, 227, 49, 251, 226, 190, 74, 117, 251, 22, 229, 1, 140, 173, 234, 126, 79, 206, 67, 169, 150, 47, 135, 212, 84, 98, 225, 148, 102, 145, 220 }
main, WRITE: TLSv1.2 Handshake, length = 70
SESSION KEYGEN:
PreMaster Secret:
0000: FB 1D 4C 57 26 1E 10 D9   57 2A 37 71 D8 B0 7A 4A  ..LW&...W*7q..zJ
0010: 1D 99 75 85 24 90 28 19   E4 B3 58 31 6E 02 B8 4A  ..u.$.(...X1n..J
CONNECTION KEYGEN:
Client Nonce:
0000: 5C 05 06 08 F6 7C 3F 5C   73 57 F0 E4 D0 A8 90 11  \.....?\sW......
0010: 3C D1 AB 9A 69 B6 4D A0   F3 13 6C 27 F5 09 80 9B  <...i.M...l'....
Server Nonce:
0000: E7 47 9B 66 69 81 2F 03   93 AE 49 BC 3C A7 97 6C  .G.fi./...I.<..l
0010: 3D D2 2E 08 5A C6 74 65   AB 97 87 DE 5F 2C E3 E1  =...Z.te...._,..
Master Secret:
0000: 99 E8 51 8A 8D A5 56 56   09 42 31 3B EA A6 25 B0  ..Q...VV.B1;..%.
0010: 69 73 EB 33 56 64 57 D1   10 86 55 1C 51 86 B2 23  is.3VdW...U.Q..#
0020: 89 51 FF 42 41 BB D5 50   FD BC EF 9B E0 10 38 3F  .Q.BA..P......8?
... no MAC keys used for this cipher
Client write key:
0000: 4C 86 23 06 D6 FA 06 BD   3C EE A2 CE 28 1F 77 9A  L.#.....<...(.w.
Server write key:
0000: 1D 93 C4 5B 2A 6D 74 F8   1C 51 23 7E 5C BA DA A9  ...[*mt..Q#.\...
Client write IV:
0000: DF 88 94 CB                                        ....
Server write IV:
0000: 5C 43 CA 31                                        \C.1
main, WRITE: TLSv1.2 Change Cipher Spec, length = 1
*** Finished
verify_data:  { 7, 235, 79, 105, 125, 222, 241, 252, 104, 122, 143, 122 }
***
main, WRITE: TLSv1.2 Handshake, length = 40
main, READ: TLSv1.2 Change Cipher Spec, length = 1
main, READ: TLSv1.2 Handshake, length = 40
*** Finished
verify_data:  { 177, 236, 151, 88, 195, 59, 82, 200, 25, 135, 145, 190 }
***
%% Cached client session: [Session-1, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]
main, WRITE: TLSv1.2 Application Data, length = 178
main, READ: TLSv1.2 Application Data, length = 540
main, called close()
main, called closeInternal(true)
main, SEND TLSv1.2 ALERT:  warning, description = close_notify
main, WRITE: TLSv1.2 Alert, length = 26
main, called closeSocket(true)
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
main, setSoTimeout(0) called
%% No cached client session
*** ClientHello, TLSv1.2
RandomCookie:  GMT: 1543833097 bytes = { 240, 7, 191, 159, 152, 93, 95, 120, 98, 108, 183, 39, 146, 177, 15, 17, 250, 215, 164, 123, 155, 232, 211, 112, 149, 107, 76, 139 }
Session ID:  {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {secp256r1, secp384r1, secp521r1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Extension server_name, server_name: [type=host_name (0), value=www.alertlogic.com]
***
main, WRITE: TLSv1.2 Handshake, length = 194
main, WRITE: SSLv2 client hello message, length = 140
main, READ: TLSv1.2 Alert, length = 2
main, RECV TLSv1.2 ALERT:  fatal, handshake_failure
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

Таким образом, рукопожатие обычно начинается с использованием TLSv1.2, но затем внезапно завершается сбоем без каких-либо объяснений.

Одно из следующих действий предотвращает сбой фрагмента:

  1. Замена URL-адреса на не-AWS endpoint.
  2. Удаление SSLv2Hello из списка поддерживаемых протоколов.
  3. Комментирование функции System.setProperty ("https.protocols", ...) полностью.

Может ли кто-нибудь объяснить, почему присутствие SSLv2Hello нарушает рукопожатие, почему оно специфично для AWS и есть ли y, чтобы решить эту проблему на нашей стороне без ущерба для нашей безопасности?

1
задан 3 December 2018 в 12:59
1 ответ

Такое поведение кажется быть преднамеренной функцией Java 7 и, возможно, некоторых других библиотек SSL / TLS.

Этот пост даст вам больше информации: Java 7 и смерть SSLv2Hello . По сути, Oracle хочет быть уверенным, что SSLv2Hello будет уничтожен навсегда, и другие (AWS), вероятно, последуют его примеру в обработке устаревшего рукопожатия.

Надеюсь, что это поможет :)

1
ответ дан 3 December 2019 в 23:09

Теги

Похожие вопросы