OpenSSL 1.0.2e: очередной критический патч и почему в этот раз мы уложились за час
OpenSSL 1.0.2e закрыл CVE-2015-3193 и несколько других уязвимостей. Автоматизированный скан через Ansible показал версии на всех серверах за минуты - патч занял час вместо рабочего дня.
OpenSSL 1.0.2e закрыл несколько уязвимостей включая CVE-2015-3193 в функции BN_mod_exp, позволявшей атаку на RSA/DH-ключи в режиме с Montgomery exponentiation
3 декабря OpenSSL Project выпустил 1.0.2e. Набор уязвимостей стандартный для таких релизов: что-то в обработке сертификатов, что-то в криптографической математике. Главная - CVE-2015-3193, ошибка в BN_mod_exp на x86-64, которая при Montgomery exponentiation выдаёт неправильный результат. На практике это означает слабость в RSA и DH: при определённых условиях атакующий может восстановить приватный ключ. Звучит академично, но это OpenSSL - он торчит из каждого сервера.
Про Heartbleed никто не забыл. После того как в 2014-м пришлось в панике выяснять на каком сервере какая версия библиотеки и вручную заходить по SSH, мы решили что второй раз так не хотим.
Что изменили после Heartbleed
Написали небольшой Ansible-плейбук для аудита. Он ходит по всему инвентарю и собирает версию OpenSSL с каждого хоста - через openssl version или dpkg -l libssl*, зависит от дистрибутива. Результат выводится в отчёт по хостам и группам.
Это несложная вещь - буквально один таск плюс debug с register. Но именно она оказалась ценной: когда появляется CVE, первый вопрос «а у кого что стоит» закрывается за несколько минут, а не за несколько часов.
Второй плейбук - сам патч. Он обновляет openssl и libssl через пакетный менеджер, проверяет версию после установки, при необходимости перезапускает зависимые службы. Параметризован по group и limit, так что можно откатить на одну группу или на конкретный хост.
Как прошло на этот раз
Когда вышел 1.0.2e, запустили аудитный плейбук. Через несколько минут был список: какие хосты на уязвимой версии, какие уже в порядке, где вообще OpenSSL не торчит наружу и можно чуть подождать.
Дальше - патч-плейбук по уязвимым хостам. Ubuntu apt-get upgrade openssl libssl1.0.0, CentOS - yum update openssl. После прогона снова аудит - убедиться что версии поднялись везде, не только там где ansible отчитался об изменении.
Весь цикл занял чуть меньше часа. Включая проверку, включая перезапуск nginx и postfix там где они были, включая финальный прогон аудита для подтверждения.
Для сравнения: после Heartbleed на аналогичный объём инфраструктуры у нас ушёл полный рабочий день - и это с авралом и сфокусированными людьми.
Что неудобно
Перезапуск зависимых служб - самая болезненная часть. OpenSSL обновляется в пакете, но запущенные процессы продолжают держать старую libssl.so в памяти. lsof | grep libssl покажет список. Для nginx это reload, для многих других сервисов - полноценный restart с прерыванием соединений.
На серверах без согласованного окна обслуживания делать restart вслепую некомфортно. Для части хостов пришлось уточнять у клиентов когда можно. Это добавляет время, но на уровне переписки и согласования, а не технической работы.
Ещё одна проблема - не все пакетные репозитории обновляются одновременно. На паре хостов с CentOS 6 зеркало запаздывало, патч появился только через несколько часов после релиза. Надо было либо ждать, либо собирать из исходников, либо временно переключать репозиторий. Выбрали подождать - уязвимость не zero-day-эксплойт, несколько часов погоды не сделали.
Что вынесли
Сам CVE-2015-3193 не имеет известного публичного эксплойта, и математика там такая что практическая атака нетривиальна. Но это не повод откладывать: OpenSSL патчится регулярно, и если каждый раз выяснять где что стоит руками, это накапливается в настоящую проблему.
Ansible-подход работает именно потому что плейбуки написаны не под конкретную CVE, а под задачу: «узнать версии» и «обновить пакет». Следующий критический патч - а он будет, история OpenSSL достаточно показательна - пройдёт по той же схеме.
Один момент остаётся нерешённым: хосты которых нет в инвентаре. Завалявшийся тестовый сервер, VPS поднятый год назад под разовую задачу, что-нибудь в DMZ с непонятной историей - они в аудит не попадают. Это скорее проблема учёта инфраструктуры чем инструментария, но она есть.
Клиентам на managed-обслуживании сегодняшний патч прошёл в рамках обычного рабочего дня - не авральный режим, не откладывание на потом. Это и было целью когда переписывали процедуру.