J3qx

information archive

Бронируем TLS в Windows Server 2012 R2

Posted by j3qx на Декабрь 8, 2014

Бронируем TLS в Windows Server 2012 R2

Привет.

Защита TLS – штука крайне нужная. У неё много аспектов – как безопасность самой хостовой ОС, на которой развёрнут веб-сервер, так и безопасность работающих приложений, криптографические аспекты и многое другое. Я попробую написать про то, что с моей точки зрения, является важным и не сильно документированным / очевидным. На этом вода про то, что с TLS лучше, чем без TLS, а с настроенным TLS лучше, чем с не настроенным TLS, официально объявляется закончившейся.

Стартовые ограничения статьи – не будет рассматриваться тюнинг SSL, т.к. уже 13 лет как есть TLS, SSL мы будем выключать полностью. Не будет рассматриваться настройка систем младше NT 6.0, т.к. про это можно найти в предыдущей статье, да и те, кто думает о безопасности TLS, наружу Windows Server 2003й в 2014м году не выставляет.

Для большинства операций я буду использовать ATcmd – им проще делать тонкий тюнинг SSL/TLS. Если хотите – можете найти другие методы по выполнению аналогичных действий на своей ОС, это некритично – функционал называется стандартно, и ту же фрагментацию TLS можно настраивать чем удобно.

Бронируем TLS в Windows Server 2012 R2

  • Версия SSL/TLS на сервере
  • Отключаем неиспользуемые версии SSL/TLS и PCT/MPUH
  • Пересогласование TLS
  • Фиксируем только нужные cipher suites
  • Блокируем небезопасные криптоалгоритмы
  • Настраиваем фрагментацию TLS
  • SSL Close-Notify
  • Журналирование TLS
  • Отправка клиенту списка доверенных CA в CTL-формате
  • Логика проверки x.509-сертификата клиента
  • Проверка промежуточных сертификатов через Интернет

Поехали.

Версия SSL/TLS на сервере

Первым делом – проведём инвентаризацию того, что умеет поддерживать SCHANNEL в Windows NT. Это будут:

  • Очень старый и просто старый варианты SSL – 2.0 и 3.0
  • Редкие и давно устаревшие PCT 1.0 и MPUH
  • Протоколы TLS 1.0, TLS 1.1, TLS 1.2 и их вариант для работы поверх UDP – DTLS

Разберемся по порядку.

Краткая история вопроса – SSL

Протокол SSL был разработан фирмой Netscape, достаточно давно. Я осознанно пропущу исторические подробности, так как они сейчас уже не особо интересны. В его задачи входило следующее:

  • Обязательность подтверждения подлинности сервером
  • Опциональная проверка подлинности клиента
  • Совместная генерация случайного сеансового ключа
  • Поддержка различных симметричных алгоритмов для шифрования данных
  • Поддержка различных алгоритмов хэширования для реализации проверки целостности через MAC

Первая версия SSL не особо показывалась публике, отсчёт рабочих версий можно начинать с SSL 2.0 (1995й год). Эта версия была первой, которая эксплуатировалась в production, и достаточно оперативно она была доработана до SSL 3.0. Заметим, что хотя это произошло достаточно давно – в 1996 году – стандарт от этого не стал общим и открытым; он оставался стандартом, разработанным конкретной фирмой Netscape, и для его использования в ряде случаев нужна была лицензия. Опубликован IETF он был недавно; RFC 6101 описывает то, что 15 лет уже стандарт де-факто для защиты сессий множества приложений. Но, по сути, с ним уже давно пора прощаться; TLS существует годы (с 1999, если быть точнее). Поддержка TLS 1.0 есть уже во всех, даже устаревших, продуктах, поэтому мы будем в явном виде отключать SSL. Пора уже закопать стюардессу.

Краткая история вопроса – PCT 1.0 и MPUH

Протокол Private Communications Technology был разработан Microsoft’ом, чтобы улучшить работу SSL 2.0 и, на самом деле, был совместим с оным в плане формата negotiation, работал лучше и безопаснее. Но важнее то, что он подтолкнул разработку TLS. Ведь по сути, на 1995й год (тогда и был предложен драфт этого протокола на стандартизацию) ситуация была простой – SSL был частной инициативой Netscape, веб нуждался в подобном стандарте, и то, что ещё один вендор начал делать “Такое же, но чуть лучше, и своё” подтолкнуло к пониманию, что если это продолжить, то будет плохо всем – будет пачка разных вариантов от разных вендоров, частично совместимая и закрытая. Это бы затормозило развитие технологий безопасной работы в Интернете, поэтому PCT благополучно похоронили, а через 3 года появился TLS. Поэтому PCT мы будем отключать в явном виде (хоть это и делается автоматически с ядра NT 6.0, но лучше сделать это явно и жестко, чем оставить на самотёк).

Multi-Protocol Unified Hello – ещё одна древняя попытка Microsoft сделать универсальный безопасный протокол типа SSL. Она совсем древняя, поэтому её тоже надо выключать в явном виде – просто чтобы исключить даже попытки её согласовать или предложить.

Краткая история вопроса – TLS 1.0, 1.1 и 1.2

В 1999 году появляется TLS 1.0. Он заменяет собой вендорский SSL 3.0, являсь очень похожим на него, и пишет в заголовок версию {0x03,0x01}, намекая, что он 3.1.

Версия 1.0, по сути, является базовой, хотя, надо отметить, напрямую TLS 1.0 и SSL 3.0 не совместимы; TLS 1.0 “умеет” работать в режиме совместимости с SSL, но именно в режиме, а не “идентично”, как иногда можно прочитать.
Например, у SSL 3.0 есть встроенная в протокол неприятность – половина master key будет создаваться из MD5-хэша достаточно предсказуемых данных, что может привести (учитывая текущее положение MD5) к успешной коллизионной атаке (в результате станет известна половина бит мастер-ключа, от которого после генерятся сессионные ключи, а это практически равнозначно компрометации процесса). У TLS 1.0 это поправили, и схема усложнена – PRF-функцией берутся и MD5 и SHA-1 хэши, после чего xor’ятся, что сводит возможность вышеуказанной атаки к нулю. Кстати, из-за этого момента в алгоритме – завязанности ключевой части процесса на MD5, SSL 3.0 не является FIPS140-2 совместимым и при включении FIPS140-2 не согласовывается, а вот TLS 1.0 – уже является. Что же ещё, помимо FIPS-совместимости и модификации PRF-функции?

  • Убрана поддержка cipher suites с алгоритмом Fortezza
  • Клиент обязан поддерживать cipher suite TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA. То есть, обязательна реализация 3DES у клиента.
  • В TLS явно и недвусмыслено описали, как именно делается padding в блочных шифрах (т.е. чем “добиваются” блоки некратной длины в CBC-варианте) – это как раз то, из-за чего для борьбы с уязвимостью POODLE (детали про неё можно посмотреть здесь) нужно отключать поддержку SSLv3.
  • В SSL не было явно указано, как защищать pre-master secret. В TLS – формализовали, поэтому разные реализации стали делать это однотипно.
  • В TLS гораздо больше возможных alert’ов со стороны сервера, поэтому клиенту “понятнее” и причины отбоя со стороны сервера, и другие проблемы при handshake.
  • Поддержка возможности получить корневой сертификат в составе certificate_list с сервера – в SSL можно было получить лишь intermediate.
  • В SSL у клиента была возможность отправлять данные некоторое время после отправки Finished. В TLS это убрали.

Поддержка TLS 1.0 сейчас является абсолютным минимумом для защищённых соединений – но со времён 1.0 много воды утекло и многое поменялось – смотрим дальше.

Промежуточными дополнительными расширениями, интересными для нас, будут RFC 3268 от 2002 года, который добавляет поддержку AES (двух основных вариантов – с 128 и 256 битами, третий штатный вариант со 192 как-то не особо прижился), и RFC 3546 от 2003 года, который добавляет пачку extension’ов, включая в себя расширение механизма handshake, добавление SNI (Server Name Indication), согласования размера TLS-фрагмента и расширенной работы с сертификатами и CRL. Его расширяет RFC 4366 от 2006 года, который добавляет ещё расширений – про них упомянём далее.

В 2006 году появляется TLS 1.1. Что он меняет?

Основное в нём – защита от найденных проблем с атаками на блочные шифры, работающие в CBC-режиме.

  • Вектор инициализации ранее считался из остатка после CBC-шифрования предыдущего блока данных. Теперь он явный и прямой зависимости от результата предыдущего шифрования не имеет.
  • Улучшена обработка padding errors – они теперь вычисляются на уровне “не совпал MAC”, а не “сбой расшифровки”, что улучшает отделение попыток атаки от технических сбоев.
  • Улучшена поддержка session resuming – возможности продолжить прерванную сессию без полной переустановки и пересогласования.

Таким образом, TLS 1.1 – некрупный багфикс TLS 1.0, поддержка которого никак особо не перегружает сервера (это я про миф про то, что “мы не держим TLS старше 1.0, потому что он дико грузит серваки”), но закрывает явно существующие уязвимости. Что далее?

В 2008 году появляется TLS 1.2. Он привносит следующие полезные штуки:

  • Связка MD5+SHA-1, используемая в предыдущих версиях, и пришедшая на замену одинокому MD5 в семействе SSL, теперь может быть заменена любым хэш-алгоритмом (предпочтительным является представитель семейства SHA-2, в частности SHA-256)
  • Поле Verify_data, по сути – PRF (PRF = pseudorandom function = почти KDF, только KDF-функция делает из чего-то ключ, а PRF рандомизирует несколько входных блоков данных в один) от master_secret, MD5 и SHA-1 хэшей данных и строчки finished_label (которая может быть или “server_finished” или “client_finished”), теперь мало того, что считается с нужным хэшем, так ещё и перестало быть ограничено 12ю байтами. Т.е. ранее от всего этого брались последние 96 бит, а теперь – столько, сколько надо, что соответственно усиливает надёжность проверки целостности данных.
  • Серьёзные изменения в криптографической части. Хэши семейства SHA-2 теперь обязательны к поддержке, а SHA-256 – рекомендуемый минимальный. Убрана поддержка алгоритмов IDEA и DES – с ними теперь TLS-сессию не согласовать, сервер откажется. Обязательным для поддержки стал cipher suite TLS_RSA_WITH_AES_128_CBC_SHA, без его наличия клиента не подключат.
  • Множественные доработки в самом алгоритме, коснувшиеся ужесточения порядка действий (отсекая потенциальные атаки, связанные с излишней гибкостью поведения алгоритма ранее), увеличения количества ситуаций, когда сервер высылает клиенту alert с описанием проблемы, а не просто отключает или игнорит блок данных. Например, теперь клиент, если у него нет сертификатов, а его запросили, не может промолчать, а обязан выслать ответ с пустым списком сертификатов.

В алгоритме также сделана необязательной поддержка SSL 2.0, а впоследствии, в 2011 году, в RFC 6176, SSL 2.0 практически отключается – клиенту явно запрещается посылать hello-запросы с протоколом ниже {0x03, 0x00}, серверу тоже запрещается их отправлять, а если к серверу они всё же приходят, он будет их игнорировать. Говоря про TLS 1.2 мы будем подразумевать его в варианте “учитывая RFC 6176″.

Фактически, TLS 1.2 – это линейное улучшение криптографических параметров TLS предыдущих версий, явное отсечение устаревших функций плюс ещё бОльшая формализация алгоритма.

После TLS 1.2 развитие TLS также не остановилось – RFC 5746 добавляет новый вариант безопасного пересогласования ключевой информации, а RFC 5878 – новые расширения для новых типов авторизации, ну а RFC 6066 актуализирует эти, ставшие уже стандартными, расширения.

Отдельно можно добавить то, что оригинальные протоколы – SSL, PCT, TLS – были нацелены на защиту TCP-трафика, но параллельно с реализацией TLS появился и DTLS, предназначенный для защиты потока датаграмм юникастового трафика (это UDP, SCTP, DCCP и RTP). В плане функционала версий DTLS 1.0 – это TLS 1.1, а DTLS 1.2 – TLS 1.2. Технически в плане безопасности отличий в нём будет минимум, поэтому отдельно про него писать не будем, упомянём лишь, что “из коробки” он доступен начиная с ядра NT 6.2, а для предыдущего поколения ОС доступен добавляющий его поддержку (только для UDP) в SCHANNEL патч – KB 2574819. Это нужно, например, для работы RDP 8.0, который умеет работать поверх UDP.

Так что материала много – вперёд, к практике.

Отключаем PCT 1.0, MPUH, SSL 2.0 и SSL 3.0

Итак, теперь практика – выключаем совсем SSL 2.0, SSL 3.0, PCT 1.0, MPUH, включаем в явном виде TLS 1.1 и TLS 1.2. С TLS 1.0 ситуация на Ваш выбор – хорошо бы его, конечно, выключить, но надо убедиться, что клиенты это выдержат. В первую очередь это коснётся мобильных клиентов, где (особенно в Android) зоопарк полуработающих реализаций TLS – дело нормальное. Хотя и десктопные не отстают – в той же Filezilla, использующей gnutls, реализацию допилили до полностью RFCшной только этим летом, 2013го года – для примера, у Microsoft это было с Windows Server 2008R2, т.е. с 2009 года. Ну, опенсорс – роль догоняющего-допиливающего-на-бегу-чтобы-хоть-кое-как-работало для них привычная, так что ничего сверхординарного.

Запустим ATcmd и выключим-включим нужное – для этого зайдём в контекст tls и выполним предсказуемые команды:
Выключаем SSL, MPUH и PCT и явно включаем TLS нужной версии

Посмотрим на результаты:

Смотрим состояние протоколов SSL, MPUH, PCT и TLS на хосте

Вполне ОК. Теперь надо тюнить выживший TLS.

Пересогласование TLS

В TLS есть интересные дополнительные механизмы, которые нуждаются в настройке. Первый из них – это пересогласование. Суть достаточно простая – во всех протоколах, которые обеспечивают конфиденциальность данных, принято время от времени менять ключи, которые используются для этой задачи. Смена их может быть разной – как частичной (например, в IPsec без PFS – когда из одного ключевого материала периодически “нарезаются” разные ключи), так и полной (когда новый ключевой материал генерится каждый раз заново). Идея в том, что эта операция – смены ключей – крайне важна и её проведение практически всегда связано с нагрузкой на CPU. В классическом TLS пересогласование мог “заказать” клиент фактически в любой момент, что и использовалось для возможной атаки (т.е. можно подключиться к серверу и заставить его малыми усилиями со своей стороны постоянно и неограниченно делать сложные вычислительные задачи).

Безопасное пересогласование TLS описывается в стандарте RFC 5746 и решает проблему с этой возможной уязвимостью.

По сути, Windows-хост может работать в плане этого RFC в двух режимах – в режиме совместимости (т.е. допускать и небезопасное, “классическое” пересогласование TLS), и в “безопасном”, допуская только пересогласование в новом формате. По умолчанию, работа идёт в режиме совместимости. Это не всегда полезно, поэтому надо знать, как включать только безопасное пересогласование TLS.

Кроме того, в данном стандарте описывается специальный workaround для старых серверов, которые не поддерживают безопасное пересогласование – таким серверам отправляется специальный псевдо-cipher-suite, называемый Signaling Cipher Suite Value (SCSV), с кодом 0x00FF. Устаревший сервер проигнорирует этот неизвестный cipher suite, а клиент догадается, что сервер старый и не умеет новый безопасный renegotiation_info.

Вообще, если уж совсем закручивать гайки, то пересогласование надо оставлять включённым только при TLS 1.2, потому что даже безопасное пересогласование при версиях TLS до 1.2й предоставляет шанс DoS на сервер. Но учитывайте – крайне много софта это не переживёт. Поэтому мы включим только безопасный вариант пересогласования и явно выключим поддержку SCSV. Если она останется, то наш TLS будет посылать “заглушку” вместо запроса возможности безопасного пересогласования.

Т.е. суть наших настроек сейчас проста – пример: надо работать только с веб-серверами, поддерживающими RFC 5746 и понимающими, что такое TLS Renegotiate extension. Важно, что это надо настраивать и на серверах, которые инициируют TLS-подключение на другие хосты (например, почтовых), ведь в этом случае они выступают как клиенты.

Включаем поддержку TLS Renegotiation Indication Extension

В том же контексте tls у нас есть команда renego, которая по вопросику покажет, что она умеет:
Включаем безопасное пересогласование TLS
Ну и явно выключим SCSV:
Выключаем SCSV в TLS
С этим вроде всё. Понятное дело, если хочется супер-защиты, то надо renego none, если не TLS 1.2.

Фиксируем только нужные cipher suites

Итак, при согласовании TLS один из ключевых моментов – это выбор комплекта допустимых cipher suites. Вот как выглядит полный список поддерживаемых в CNG наборов:

TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_RC4_128_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P521
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P521
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P384
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P521
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P384
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P521
TLS_DHE_DSS_WITH_AES_128_CBC_SHA
TLS_DHE_DSS_WITH_AES_256_CBC_SHA
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_RC4_128_MD5
SSL_CK_RC4_128_WITH_MD5
SSL_CK_DES_192_EDE3_CBC_WITH_MD5
TLS_RSA_WITH_NULL_SHA
TLS_RSA_WITH_NULL_MD5

TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P521
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P521
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P384
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P521
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P384
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P521
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
TLS_RSA_WITH_NULL_SHA256

TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P256
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P521
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P384
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P521

Внушительно. Надо сокращать. Первым делом – убираем все те, кто содержит в себе:

    • NULL – этот вариант, когда согласуется “SSL без шифрования”, нам категорически не подходит.

 

    • DES / 3DES / RC4 – данные варианты на фоне ощутимо более быстрого и надёжного AES, который к тому же на современных процессорах аппаратно ускоряется, не интересны.

 

  • MD5 / SHA-1 – даже XP с нужным патчем поддерживает хэши семейства SHA-2, поэтому нет смысла предлагать и поддерживать старые варианты, тем более, что выбор MD5, допустим, выглядит странно – учитывая, что даже в TLS 1.0 хэш был MD5+SHA-1, явный выбор одинокого MD5 – удивителен.

Список сразу сокращается:

TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P521
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P521
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P384
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P521
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P384
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P521

TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P521
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P521
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P384
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P521
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P384
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P521
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256

TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P256
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P521
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P384
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P521

Не забудем в пылу борьбы, что для согласования TLS 1.0 надо обязательно оставить TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, а TLS 1.2 – TLS_RSA_WITH_AES_128_CBC_SHA. Т.е. в зависимости от того, включим ли мы TLS 1.0, нам придётся добавить первый из упомянутых либо нет. Список все равно внушительный, поэтому при его дальнейшем урезании будем исходить из следующих соображений.

    1. ECDHE лучше, чем DHE, благодаря дополнительной “степени защиты” в виде усложнения алгоритма генерации ключевого материала (при помощи эллиптических кривых). Генерация ключевого материала – по сути, самое важное, т.к. лобовая атака на AES – крайне маловероятна, а вот на предсказуемость генерации ключа – гораздо более реалистична. Мы не можем явно выбрать группу DH, а то бы, конечно, по меньшей мере отказались от групп 1,2,5 и выбрали бы 16, ну или 14-15, но нам тут такой выбор не предоставляется, поэтому, чтобы форсировать группы на 19-20ю, мы выберем ECDHE.

 

    1. AES-128 надо предпочесть AES-256 в исключительно редком варианте, когда криптографические вычисления (в силу огромного потока трафика) нагружают CPU так, что это является критичным. Хотя в таком случае лучше подумать о более серьёзном процессоре, ну или балансировке нагрузки, но тут как получится уж – а мы пока остановимся на AES-256.

 

    1. Выбор хэша из SHA-2 (SHA-256 или SHA-384 или SHA-512) – по сути, меньше всего влияющее на безопасность трафика дело, т.к. что на SHA-256, что на более старшие хэши, атаки именно на фальсификацию “на лету” пока особо не придумано. Нам важнее, чтобы быть более защищённым в ситуации “кто-то полностью заснифил сессию и в оффлайне хочет расшифровать её содержимое”, а тут хэш особо не интересен. Поэтому я бы предложил остановиться на SHA-256, исключительно по причине сомнительности траты ресурсов на данную задачу.

 

  1. AES-GCM лучше, чем AES-CBC, но он бывает только в TLS 1.2, исключительно. Поэтому оставлять его как единственный вариант – правильно лишь при абсолютной уверенности, что все хосты, взаимодействующие по TLS, поддерживают 1.2 со всеми “новшествами”.

Что получится?

TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P521

TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P521

Плюс, понятное дело, TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA и/или TLS 1.2 – TLS_RSA_WITH_AES_128_CBC_SHA. Согласование пойдёт со “старших” cipher suites, поэтому данная ситуация будет гораздо лучше, чем дефолтная. Действуем. В данном варианте нам надо будет зайти в настройку групповых политик (или в локальную политику, если хочется), выбрать там Computer Configuration -> Administrative Templates -> Network -> SSL Configuration Settings -> SSL Cipher Suite Order и указать нужные cipher suites – как положено по инструкции, через запятую и без пробелов, начиная с самых стойких. Строка ограничена 1023 символами, но нам их, после секвестра списка, вполне хватит.

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

Блокируем небезопасные криптоалгоритмы

В Windows поддерживается множества криптоалгоритмов, которые на данный момент уже совсем не нужны. Например, есть поддержка хэшей MD2 и MD4 – они использовались в ранних реализациях стека IPsec (который для Windows 2000 разрабатывала компания Cisco, поэтому он с первой же версии работал, а не как иногда бывает), а сейчас абсолютно не актуальны. Или классический DES, который в силу роста вычислительных мощностей, да и того, что в ключе из 64 бит только 56 являются уникальными, уже не безопасен, т.к. его bruteforce доступен коммерческим заказчикам. Или замечательные по стойкости шифры RC2 на 40 и 56 бит, или RC4. В общем, мы в явном виде “убьём” в системе следующие криптоалгоритмы: NULL, RC2, RC4, DES, MD2, MD4. На всякий случай, так сказать.

Настраиваем фрагментацию TLS

При обмене TLS передаёт данные сообщениями (message). Максимальный размер данных сообщений ограничен в TLS 1.0 – и равен 16.384 байт. Если какое-либо сообщение (не данные, а всё, включая заголовки) больше этого числа, то включается механизм фрагментации TLS (не путайте с IP-фрагментацией). Данный механизм изначально поддерживается в NT 6.1 (Windows 7 и Windows Server 2008 R2) – для остальных систем нужен патч KB 2541763.

Проблема в том, что у разных серверов данное значение может быть разным – да и у клиентов (особенно мобильных) – тоже. На практике встречаются значения от 8192 байт (половинный стандарт, такое было на WinMobile) до 32768 байт (некоторые web-сервера). Поэтому нам нужно заранее подготовиться к этому, разрешив обработку фрагментов крупного размера. Это повлияет на многое – простейший пример; сервер считает, что максимальный размер фрагмента – 32К, и отдаёт в процессе TLS-handshake’а пачку сертификатов (он же имеет право ознакомить клиента с цепочкой оных, чтобы упростить ему проверку подлинности предъявляемого своего серверного сертификата), которая в сумме весит 20К. А клиент принимает только до 16К. Результат – отбой сессии на фазе установления.

Что мы можем настроить? Три значения – максимальный размер TLS-фрагмента, который мы отправляем, если мы:

    • TLS-клиент (параметр client)

 

    • TLS-сервер для клиента, который не аутентифицировался при помощи предъявления x.509 – сертификата (параметр server)

 

  • TLS-сервер для клиента, который аутентифицировался при помощи предъявления x.509 – сертификата (параметр serverauth)

Делается это несложно:

Настройка TLS-фрагментации

Замечу также, что данные значения имеют максимумы (соответственно, в порядке указания, 32К, 16К, 32К – т.е. фрагменты максимально могут быть до 32К, за исключением случая подключения неаутентифицирующегося клиента) и связаны следующей логикой – для определения максимального размера фрагмента в последнем из сценариев (подключение клиента, подтверждающего свою подлинность сертификатом) берётся максимальное значение из пары server / serverauth.

Установим всё в максимальные значения, чтобы принимать все возможные фрагменты, и продолжим.

Анти-BEAST или принудительная TLS-фрагментация

В 2012 году для обработки специфичной атаки (тот самый BEAST) фирма Microsoft выпустила специальный патч, который добавлял дополнительное управление фрагментацией (уже не размером фрагмента, а самой логикой работы оной) в SCHANNEL. В принципе, атака BEAST отражается просто – надо не использовать TLS 1.0 и SSL 3.0, а использовать только TLS 1.1 и выше, но это легко сказать, но трудно реализовать в современном интернете, где куча опенсорсных поделок годами работают с устаревшими и уязвимыми реализациями протоколов и стандартов, исходя из отговорок вида “раз вообще хоть кое-как работает, то работает идеально, это же СПО”. Поэтому да, если бы все системы, подключающиеся по TLS, были бы хотя бы Windows 7 или Windows Server 2008 R2, можно было бы просто включить только TLS 1.2 и автоматически решить огромное число проблем – но увы, приходится делать это иначе.

После установки данного патча (это KB 2638806 или, если сразу для всех платформ и подробнее – MS12-006 / CVE-2011-3389) у нас появляется возможность выбрать из нескольких вариантов. Первый и используемый по-умолчанию вариант – это “В случае, если другая сторона подтверждает отправкой флага при установке SSL/TLS-сессии, что тоже установила этот патч и настроена его использовать, фрагментировать handshake так, чтобы избежать использования атаки BEAST на блочные шифры”. Т.е. говоря проще, если данный патч везде установлен, всё происходит само. Два других варианта – это принудительно фрагментировать handshake всегда или никогда.

Мы бы, конечно, выставили “всегда”, но всё же это повлечёт много проблем с совместимостью, да и не забываем, что все эти пляски интересны только если у нас исключительно TLS 1.0, на старших версиях этой проблемы уже нет. Поэтому выставим в явном виде дефолтный режим:

Выставляем TLS SendExtraRecord в opt in

Теперь далее.

SSL Close-Notify

Когда клиент закрывает TLS-сессию, есть два варианта поведения со стороны сервера – полноценно закрыть её и сэкономить силы, “прикрыв на время”, чтобы в случае переподключения того же клиента продолжить работу с ним, не выполняя “с нуля” всю криптографическую и математически интенсивную работу – генерацию ключевого материала и подобное. Это поведение можно настроить, влияя на параметр SSL Close-Notify.

По умолчанию включён “облегчённый” режим – мы включим полновесный, так как это закроет целый класс атак на truncation – игры с манипуляцией длинами ответов и запросов.

Обработка Close-Notify в TLS

Обращу внимание, что включение этого режима, по сути, обозначает так же и то, что мы, как сервер, будем не только обрабатывать клиентский Close-Notify, но и будем отправлять клиенту явное уведомление о том, что закрываем сессию и новая будет создаваться “с нуля”.

Журналирование TLS

Подсистема SCHANNEL, которая отвечает в ОС на базе Windows за встроенную реализацию TLS, может сообщать о своих ошибках и проблемах в отдельный журнал. Для отслеживания результатов наших настроек, да и вообще, чтобы не пропустить критичные ошибки, настроим это журналирование:

Настройка журналирования TLS

Отправка клиенту списка доверенных CA в CTL-формате

Когда клиент подключается к серверу, тот может предоставить ему список тех issuers, кому сервер доверяет. Это и логично – в случае, если клиент имеет широкие возможности по аутентификации при помощи x.509-сертификатов, данный список поможет автоматически уменьшить список потенциально пригодных для подтверждения своей подлинности сертификатов.

Однако, начиная с NT 6.2, данная практика считается небезопасной и отправка этого списка отключена по-умолчанию. Это, кстати, ещё и ускоряет установление соединения.

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

Отключение отправки списка issuer CA в виде CTL клиенту

Логика проверки x.509-сертификата клиента

Обычно этот момент не очень акцентируется в логике установки SSL/TLS-соединения – подразумевается что-то типа “ну, клиент должен предоставить нормальный такой сертификат”, не уточняя, что точно имеется в виду под этим. Давайте разберёмся.

Понятно, что сертификат клиента должен быть валидным на базовом уровне – т.е. правильного формата, не просроченный, не потерявший целостность, обладающий всеми обязательными полями. Но в остальном критерии “подходящий” могут быть разными. Мы можем влиять на логику проверки, выбирая один из трёх вариантов:

  • Проверка цепочки доверия сертификата клиента считается удачной, если цепочка закончилась на сертификате, входящем в Trusted Issuers (например, IIS-серверу предоставили CTL-файл с ними в явном виде) (это параметр machinetrust)
  • Проверка цепочки доверия сертификата клиента считается удачной, если цепочка закончилась на сертификате, входящем в Trusted Issuers и являющимся корневым (т.е. самоподписанным) (это параметр exclusiveroot)
  • Проверка цепочки доверия сертификата клиента считается удачной, если цепочка закончилась на сертификате, входящем или в Trusted Issuers, или в локальное хранилище сертификатов (это параметр exclusiveca)

Что выбрать в конкретном варианте – нужно смотреть для каждой ситуации отдельно, но например вариант exclusiveroot будет увеличивать время процессинга, игнорируя то, что сертификат клиента уже признан валидным, т.к. подписан валидным intermediate CA, но будет добавлять безопасности, т.к. валидация intermediate CA, по сути, будет постоянной и принудительной.

Вы сможете повлиять на это командой clienttrust в контексте tls:

Логика проверки сертификата клиента

Не забудьте, что этот параметр влияет только на ситуации, когда клиент подтверждает свою подлинность сертификатом. И это необязательно лобовой сценарий “Кто-то с токеном удалённо подключается к корпоративному порталу” – это, например, 802.1x в случае, когда машинам раздали сертификаты. Это wifi, когда клиенты с сертификатами и EAP-TLS / PEAP. Будьте осторожны с тюнингом таких параметров, и первоначально точно выясните, на что это повлияет на данном конкретном сервере.

Проверка промежуточных сертификатов через Интернет

Когда клиент предъявляет свой сертификат, мы проверяем всю цепочку доверия, пока не натолкнёмся или на ошибку, или на явно доверенный сертификат. Однако, не все родительские сертификаты могут быть у нас (сервера) локально – возможно, что проверка цепочки клиента повлечёт за собой необходимость загрузить сертификат (или несколько) по указанному URL’у.

Это действие не всегда нужно или полезно – например, публичному серверу при такой логике работы можно сделать интересную проблему, заставляя его пачками пытаться загружать сертификаты с удалённого и медленного сервера, создавая множественные “потихоньку открывающиеся” SSL/TLS-соединения. В ряде же ситуаций – допустим, когда к серверу должны подключаться только свои, корпоративные клиенты, предъявляя свои, местные сертификаты, вопрос о том, надо ли серверу обращаться в Интернет, чтобы узнать про их подлинность, вообще исключается.

Мы сделаем настройку как раз под такой сценарий – выключим возможность подгрузки intermediate CA certificates из Интернета.

Загружаем сертификаты промежуточных CA только из локального хранилища

В общем-то, пока всё. :)

Заключение

Настройка, защита и оптимизация TLS – это важный момент для обеспечения безопасности практически любой современной IT-системы, т.к. эти протоколы по сути лидируют в количество серверных продуктов, использующих их как защиту для передачи данных. Как видно, помимо “просто включить и не париться” есть много других моментов, нужных для эффективной работы. Надеюсь, что эта статья чем-то поможет.

Удачного применения знаний!

WBR, Ruslan V. Karmanov.

© http://www.atraining.ru/tls-armoring-windows-server/

 

Реклама

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

 
%d такие блоггеры, как: