На пентесте инфраструктуры финтех-компании в начале 2025 года нашли HAProxy, который спокойно принимал соединения по TLS 1.0 с cipher suite
TLS_RSA_WITH_3DES_EDE_CBC_SHA. Основной nginx стоял идеально - TLS 1.3, AEAD-шифры, HSTS с preload. А балансировщик, развёрнутый три года назад и не попавший в scope последнего аудита, открывал путь для downgrade-атаки. Раннее утро понедельника - демонстрация перехвата сессионных токенов через понижение протокола заняла четыре часа. Ни один алерт в SIEM не сработал, потому что TLS handshake с устаревшей версией никто не мониторил. По MITRE ATT&CK это Downgrade Attack (T1689, Defense Evasion), по OWASP - прямое попадание в A02:2021 Cryptographic Failures. Ниже - конкретные шаги, которые закрывают эту проблему: от выбора cipher suites до detection-правил.Настройка TLS cipher suites: что оставить, что отключить
Cipher suites в TLS 1.3
В TLS 1.3 с выбором шифров всё стало проще некуда. Протокол поддерживает три cipher suite:TLS_AES_256_GCM_SHA384, TLS_AES_128_GCM_SHA256 и TLS_CHACHA20_POLY1305_SHA256. Все три - AEAD-режим, Perfect Forward Secrecy по умолчанию, fallback на слабые алгоритмы невозможен. Директива ssl_ciphers в nginx для TLS 1.3 не работает - протокол сам управляет набором. Единственное, что нужно настроить - supported_groups (ранее elliptic_curves в TLS 1.2, переименовано в RFC 7919; RFC 8446 §4.2.7). Эта штука согласует группы для key exchange: x25519 как приоритетная, secp256r1 и secp384r1 как fallback. В nginx директива ssl_ecdh_curve X25519:secp256r1:secp384r1; управляет списком для обеих версий TLS.Отключение слабых шифров в TLS 1.2
С TLS 1.2 всё сложнее: протокол поддерживает десятки cipher suites, и большинство из них небезопасно. На основе профиля Mozilla Intermediate (актуален на 2025 год) рабочая конфигурация nginx:
NGINX:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
ssl_ecdh_curve X25519:secp256r1:secp384r1;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_stapling on;
ssl_stapling_verify on;
- Только ECDHE для обмена ключами - RSA key exchange убран полностью. PFS работает: компрометация серверного ключа в будущем не раскрывает ранее перехваченный трафик
- Только GCM и CHACHA20 - CBC-режим выброшен, BEAST и Lucky13 закрыты
ssl_prefer_server_ciphers off- в TLS 1.3 директива игнорируется, для TLS 1.2 это рекомендация Mozilla Intermediate. Хотите приоритизировать CHACHA20 на мобильных клиентах без AES-NI - используйтеssl_conf_command Options PrioritizeChaCha;(nginx 1.19.4+ с OpenSSL 1.1.1+)
На Windows Server порядок cipher suites управляется через Group Policy (Computer Configuration -> Administrative Templates -> Network -> SSL Configuration Settings -> SSL Cipher Suite Order) или PowerShell-командлеты модуля TLS. Список ограничен 1023 символами, изменения вступают в силу только после перезагрузки - планируйте maintenance window. Для IIS удобен IIS Crypto с предустановленными шаблонами: Best Practices, PCI 4.0, FIPS 140-2.
Протоколы SSLv2, SSLv3, TLS 1.0, TLS 1.1 и cipher suites с RC4, DES, 3DES, EXPORT, NULL должны быть отключены безусловно на всех endpoint. Если
testssl.sh показывает хотя бы один из этих шифров - находка категории High, без вариантов.Типичные ошибки TLS конфигурации в production
HTTP между балансировщиком и бэкендом
Самая частая ошибка TLS конфигурации - HTTPS-терминация на балансировщике с передачей plain HTTP на бэкенд. Формально сертификат есть, Qualys SSL Labs показывает A+, а трафик между HAProxy и nginx идёт без шифрования по внутренней сети. Атакующий с доступом к сетевому сегменту (Network Sniffing, T1040 по MITRE ATT&CK) видит всё в открытом виде.Решение - end-to-end TLS. На бэкенде поднимается отдельный сертификат (допустим внутренний CA), балансировщик подключается по HTTPS. Накладные расходы на CPU с современным железом с AES-NI - 2-3%. Это давно не аргумент для отказа.
HSTS preload: пошаговая настройка без катастроф
HSTS - единственная реальная защита от SSL stripping. Без него атакующий на позиции Adversary-in-the-Middle (T1557) перехватывает первый HTTP-запрос до редиректа на HTTPS и подменяет соединение.Типичные ошибки при настройке HSTS preload:
max-age=0- фактически выключает HSTS- Нет
includeSubDomains- субдомены остаются открыты для SSL stripping - Включение
preloadбез проверки всех субдоменов - после попадания в preload-список откат требует прохождения через цикл релизов всех major-браузеров. Это месяцы, иногда больше года. Решение фактически необратимо в обозримом горизонте
max-age=300 на неделю для тестирования, проверяете все субдомены на поддержку HTTPS, затем выставляете max-age=31536000; includeSubDomains; preload и подаёте заявку через hstspreload.org.OCSP stapling и DH-параметры
Без OCSP stapling браузер клиента сам лезет к OCSP-серверу CA проверять отзыв сертификата. Это утечка метаданных плюс задержка. Если OCSP-сервер недоступен, часть браузеров молча принимает сертификат в режиме soft-fail - механизм отзыва превращается в пустышку. Проверка работоспособности stapling:openssl s_client -connect host:443 -status, смотрим поле OCSP Response Status в выводе.Для DHE cipher suites (не ECDHE) - если они ещё включены - сервер по умолчанию может использовать 1024-битные DH-параметры, уязвимые для атаки Logjam. Генерация 2048-битных:
openssl dhparam -out dhparam.pem 2048 или предварительно рассчитанные ffdhe2048 от Mozilla. Оптимальный вариант - полный отказ от DHE в пользу ECDHE. Тогда DH-параметры не нужны вообще.Certificate pinning реализация: что работает, а что уже нет
HPKP мёртв - Certificate Transparency как замена
HTTP Public Key Pinning (HPKP) объявлен deprecated в Chrome 67 (май 2018) и удалён в Chrome 72 (январь 2019). Причина - катастрофический операционный риск: ошибка в пинах или потеря ключа блокировала сайт на срок max-age. Несколько публичных инцидентов с блокировкой production на недели похоронили технологию.Сейчас основная защита от поддельных сертификатов - Certificate Transparency (CT). Все публичные CA обязаны логировать выданные сертификаты в CT-логи, браузеры проверяют наличие Signed Certificate Timestamps (SCT). Для SOC это конкретный вектор мониторинга: crt.sh позволяет отслеживать выпуск сертификатов для ваших доменов. Появился сертификат от CA, которого вы не используете - потенциальный индикатор атаки Digital Certificates (T1587.003, Resource Development).
Pinning в мобильных приложениях и API-клиентах
Certificate pinning остаётся актуальным для мобильных приложений и API, где контролируются обе стороны соединения. Реализация через OkHttp (Android) и TrustKit (iOS) пинит не leaf-сертификат, а публичный ключ промежуточного или корневого CA - такой пин переживает ротацию leaf-сертификата.Критический момент: при смене CA (например, при переходе Let's Encrypt между промежуточными сертификатами) приложение с захардкоженным пином перестаёт подключаться. В production это выглядит как массовый отказ мобильного клиента без единой серверной ошибки. Правило - всегда пинить минимум два ключа (текущий и backup CA), ротацию планировать через force-update приложения.
Ограничение PKI certificate pinning: технология защищает от Adversary-in-the-Middle с поддельным сертификатом, но если атакующий установил корневой сертификат на устройство (Install Root Certificate, T1553.004) - pinning обходится. На Android с root-доступом Frida снимает pinning за минуты - стандартная техника при пентесте мобильных приложений.
mTLS: mutual authentication для zero-trust
Mutual TLS (mTLS) - двусторонняя аутентификация, где сервер тоже проверяет клиентский сертификат. В microservices-архитектуре (Istio, Linkerd) mTLS стал стандартом для inter-service communication.В nginx mTLS настраивается через
ssl_client_certificate и ssl_verify_client on. Но операционная сложность - в жизненном цикле клиентских сертификатов. Без автоматизации через PKI (HashiCorp Vault, step-ca) это превращается в ручную возню с просроченными сертификатами, которые ломают сервисы в 3 часа ночи. Проходили, знаем.TLS fingerprinting обнаружение и detection-правила для SIEM
JA3/JA4 для поведенческой аналитики
TLS fingerprinting (JA3 от Salesforce, 2017 и JA4 от FoxIO, 2023) - хеш параметров ClientHello: версия, список cipher suites, расширения, кривые. JA3 работает на любых версиях TLS, но для TLS 1.3 даёт менее стабильные результаты из-за GREASE и шифрованных расширений. JA4 - более устойчивая замена, лучше справляется с TLS 1.3 и QUIC. Каждый TLS-клиент оставляет уникальный отпечаток.Для SOC тут конкретная польза: если C2-фреймворк использует нестандартную TLS-библиотеку (Symmetric/Asymmetric Cryptography, T1573.001/T1573.002 по MITRE ATT&CK), его JA3-хеш отличается от легитимных браузеров. Baseline JA3-хешей корпоративных endpoint позволяет алертить на появление неизвестных клиентов.
Сложность на практике: JA3 меняется с каждым обновлением браузера. JA4 частично решает проблему за счёт более стабильной структуры хеша, но автоматизация обновления whitelist - обязательна. Без неё утонете в ложных срабатываниях после каждого Patch Tuesday.
Detection-правила для конкретных сценариев
Алерты, которые закрывают описанные TTPs:- TLS Downgrade (T1689) - обнаружение TLS 1.0/1.1 handshake на endpoint с настроенным TLS 1.2+. Источник: логи балансировщика, Zeek (фильтр по полю
ssl.versionсо значениями TLSv10/TLSv11), Suricata. В MaxPatrol SIEM и Elastic SIEM создаётся правило корреляции на событие SSL/TLS с версией протокола ниже порога. - Unknown JA3/JA4 Hash - появление хеша, отсутствующего в baseline. Zeek генерирует JA3-хеши через скрипт salesforce/ja3 на GitHub или плагин spicy-analyzers; для Suricata - поддержка через ja3 keyword (с версии 4.1+, нужно включить
app-layer.protocols.tls.ja3-fingerprints: yesв suricata.yaml - по умолчанию выключено). Ложных срабатываний будет много после обновлений браузеров. - Несанкционированный сертификат - новый сертификат для домена организации от CA, не входящего в approved list. Источник: интеграция с crt.sh API, Google Certificate Transparency monitoring.
- Просроченный или самоподписанный сертификат - на внутренних сервисах. Nessus, OpenVAS, Qualys детектируют при сканировании; встроенные корреляции есть в MaxPatrol SIEM, Elastic SIEM, Splunk ES.
- Weaken Encryption (T1600) - использование cipher suites со слабым шифрованием (RC4, DES, NULL) в TLS-сессиях. Zeek: фильтрация по полю
ssl.cipherс маской на известные слабые шифры.
Требования к окружению для аудита
Для воспроизведения аудита TLS-конфигурации:- ОС: GNU/Linux (Kali, Ubuntu 22.04+), macOS - для
testssl.shиsslyze - RAM: 512 МБ минимум (инструменты легковесные)
- Сеть: доступ к целевым endpoint по TCP/443
- Зависимости: OpenSSL 1.1.1+ (для проверки TLS 1.3), Python 3.8+ (для
sslyze) testssl.sh- bash-скрипт, работает offline после клонирования репозиторияsslyze- ставится черезpip install sslyze, выдаёт JSON для автоматизации в CI/CD
testssl.sh --full --json-pretty output.json https://target.com. На выходе - JSON-отчёт, пригодный для импорта в SIEM или включения в отчёт по аудиту.Чеклист TLS харденинга для передачи в эксплуатацию
Нумерованный список действий для включения в отчёт по аудиту или передачи сисадмину:
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Каждый пункт верифицируется через
testssl.sh или sslyze с сохранением отчёта. Если хотя бы один пункт не выполнен - конфигурация не считается захардененной.По опыту аудитов за последние полтора года: главная проблема TLS-харденинга не техническая, а организационная. Настроить nginx или Apache по чеклисту выше - час работы. Но в типичной enterprise-инфраструктуре TLS терминируется на десятках точек: веб-серверы, API-гетвеи, балансировщики, VPN-концентраторы, почтовые relay, внутренние сервисы с web-интерфейсами. Команда, которая захарденила основной сайт и отчиталась, нередко пропускает внутренние endpoint - те самые, где трафик уже внутри периметра и якобы "не нуждается в шифровании".
Вторая неудобная вещь: разовый аудит TLS - это ритуал, а не защита. Конфигурация дрейфует при каждом деплое, каждом обновлении, каждом новом сервисе, который кто-то поднял "на посмотреть" и забыл. Без continuous monitoring - Zeek/Suricata для анализа реальных handshake, Sigma-правила для TLS downgrade, автоматические сканы
testssl.sh в CI/CD pipeline - через три месяца после идеального аудита вы снова обнаружите TLS 1.0 на каком-нибудь забытом endpoint. Detection-часть в чеклисте не менее критична, чем hardening-часть: без неё вы не знаете, что конфигурация уже уехала от baseline. Если вы строите мониторинг TLS-конфигураций в гетерогенной инфраструктуре - на codeby.net коллеги обсуждают практику автоматизации аудита cipher suites и делятся конфигурациями Sigma-правил под детекцию TLS-аномалий в разных SIEM-стеках.
Последнее редактирование модератором: