HTTPS: Как поддерживать все протоколы SSL / TLS и комплекты шифров? - PullRequest
2 голосов
/ 22 мая 2019

Я работаю над сканером, который должен отправлять запросы HTTPS на различные серверы. Поэтому я бы хотел, чтобы мой сканер поддерживал все возможные протоколы / шифры.

В настоящее время я использую Java 8, но готов обновиться (не думаю, что это имеет значение).

Я создал SSLContext следующим образом:

SSLContext sslContext = SSLContext.getInstance("TLSv1.2");

Полагаю, что каждый сервер, поддерживающий TLSv1.3, также поддерживает 1.2.

Это будет обратно совместимо? то есть поддержка TLS 1.1 / 1.0 и SSL?

(Кстати, в наши дни ли вообще используется SSL?)

Что еще мне нужно сделать, чтобы пообещать успешное рукопожатие SSL / TLS?

Спасибо!

1 Ответ

2 голосов
/ 22 мая 2019

В связи с этим я бы хотел, чтобы мой сканер поддерживал все возможные протоколы / шифры.
В настоящее время я использую Java 8, но хочу обновить (не думаю, что это имеет значение).

Полагаю, что каждый сервер, поддерживающий TLSv1.3, также поддерживает 1.2.
Это будет обратно совместимо? то есть поддержка TLS 1.1 / 1.0 и SSL?
(Кстати, в настоящее время SSL даже используется?)

Да, по крайней мере, в ближайшем будущем почти все, кто поддерживает 1.3, также будут поддерживать 1.2, за исключением нескольких сайтов, настроенных специально для тестирования совместимости 1.3. (Держу пари, многие даже продолжат поддерживать 1.1, например, PCI все еще позволяет это, хотя и неохотно, но вам это не нужно; любая Java, поддерживающая 1.1, также поддерживает 1.2.) Контекст TLSv1.2 поддерживает более низкие версии (если это разрешено) см. ниже), и контекст TLS по умолчанию также поддерживает 1.2 и ниже в j8 (по умолчанию в j7 did не поддерживает 1.1 и 1.2 на стороне клиента) ,

Никто не должен использовать SSLv3 с 2016 года, самое позднее , а выпуски Java, начиная с j8u31 в 2014-12 годах, были настроены для его запрета, хотя код все еще присутствует, если вы измените конфигурацию, чтобы разрешить его. См. Запись для jdk.tls.disabledAlgorithms в JRE/lib/security/java.security для j8 или JAVA/conf/security/java.security для j9 up. Обратите внимание, что этот тип 'disable' нельзя отменить с помощью кода, вызывающего SSLSocket.setEnabledProtocols и связанных с ним методов, только путем изменения конфигурации или свойства безопасности при запуске; в отличие от протоколов «отключен» по выбору контекста может быть включен при желании, и наоборот.

Никто не должен был использовать SSLv2 с начала века (или 2000, или 2001, в зависимости от того, насколько вы педантичны; в этом случае разница не имеет значения). Ява не (и никогда) не реализовала это так или иначе.

Использование TLSv1.0 в это время является спорным. Теоретически он уязвим для BEAST, но это, в конце концов, не представляет особой опасности и в настоящее время значительно смягчается путем разделения данных приложения на 1 / n. Поскольку Java включает его по умолчанию, я бы не стал его удалять, но вы можете быть несколько осторожны с любыми серверами, которые на самом деле его выбирают.

Вы не можете поддерживать все наборы шифров, потому что Java не реализует их все; К счастью, вам не нужно. Никто в Интернете не использует PSK (кроме варианта для возобновления в 1.3) SRP или Kerberos; Java реализует только последнее. Вероятно, ни один или очень немногие требуют Camellia SEED ARIA IDEA или AES-CCM, ни один из которых не реализует Java (по крайней мере, в стандартных криптопровайдерах), хотя вы можете столкнуться с некоторыми, которые поддерживают по крайней мере некоторые из них, если они предлагаются. Никто не должен поддерживать RC4, наборы 'export', 'eNULL' и single-DES; Снова выпуски Java запретили RC4 в java.security 8u60 в 2015-08 и по умолчанию отключил другие в течение длительного времени, наряду с «анонимными» наборами (иначе «aNULL»). Этот последний - единственный, который я хотел бы изменить; Я могу вообразить редкие, но разумные случаи для запуска общедоступного сервера без проверки подлинности сертификата, но в остальном безопасным.

Но есть и другие параметры безопасности, кроме протокола и шифра, которые могут препятствовать соединению. В частности, Java теперь настроен на отклонение рукопожатий с использованием ключа или параметров, слишком коротких, чтобы быть защищенными, или сертификатов, подписанных с использованием MD5, который не используется для этой цели, даже если они используются в наборе шифров, приемлемом для обеих конечных точек. Эти настройки аналогичны disabledAlgorithms с настройками для сертификатов и в jdk.certpath.disabledAlgorithms, и вам может потребоваться ослабить их. Существует некоторый риск того, что ваши соединения, использующие ослабленные параметры, могут быть скомпрометированы, но, поскольку вы, вероятно, не располагаете какой-либо конфиденциальной информацией для отправки на неизвестные серверы, и не будете доверять какой-либо информации, которую вы получаете от них, такой компромисс может не быть проблема.

Следующим и, вероятно, самым большим является проверка сертификата. Вы столкнетесь с большим количеством сайтов, использующих сертификаты, которые на самом деле недействительны, и многие другие, которые невозможно проверить по стандартному хранилищу доверенных сертификатов Java JRE/lib/security/cacerts или аналогичному, например, Windows или Mozilla. Поскольку вы, вероятно, не заботитесь о том, что вы на самом деле получаете данные с реального или законного сервера, вы можете игнорировать ошибки сертификата, используя ненулевую ошибку TrustManager, которая просто возвращает успех, фактически не проверяя цепочку сертификатов сервера вообще. Если вы будете искать другие Q на SO, вы, вероятно, найдете сотню, где кто-то предлагает «решить» проблему TLS или https в Java, «просто вырезая и вставляя этот TrustManager, чтобы исправить все проблемы без каких-либо мыслей, понимания или усилий». Во многих случаях это предлагается людьми, которые на самом деле не понимают TLS, для проблем, которые не являются первоочередными проблемами, поэтому «решение» не помогает, а просто делает систему полностью незащищенной, если и когда актуальные проблемы исправлены. Я думаю, что ваш первый вопрос, который я видел, где это решение действительно уместно.

Наконец, в TLS есть номинально необязательная функция индикации имен серверов (SNI), которая требуется многим серверам, особенно CDN, WAF, IDS / IPS и аналогичным, которые обрабатывают трафик для нескольких доменов. В зависимости от того, какие API и опции вы используете для создания соединений, более старые версии Java не всегда отправляли SNI. Однако, недавний j8 и выше должен делать это, если вы не намеренно отключите его - и вы можете найти некоторые сломанные серверы, где вам do нужно отключить его , как этот недавний Q .

...