Инциденты и уязвимости
Heartbleed (CVE-2014-0160) — когда из фундамента шифрованного трафика утекала память
В 2014 году в OpenSSL (на котором держится HTTPS) обнаружили Heartbleed — утечку памяти сервера, вплоть до приватных ключей и сессий. Как работал баг «возвращает больше запрошенного» и уроки: считайте, что утекло всё, перевыпускайте сертификаты, ротируйте каждый секрет.
Возвращаемся к знаковому событию ради уроков, которые всё ещё применимы к вашей эксплуатации — защитно, а не как воспроизведение.
Что произошло — «возвращает больше запрошенного»
В TLS (шифровании за HTTPS) есть keep-alive обмен «heartbeat». Клиент отправляет немного данных плюс длину («верни это обратно»), а сервер эхом отвечает — просто по замыслу.
Реализация в OpenSSL не валидировала заявленную длину. Отправьте несколько байт, но заявите «верни 64KB» — и сервер читает за пределами ваших данных в соседнюю память и возвращает её. Если там лежал приватный ключ или сессия, они тоже утекали.
Нормально: отправленная длина = возвращённая длина
«верни 'bird' (4 символа), длина 4» → сервер: «bird»
Heartbleed: крошечный payload + огромная заявленная длина
«верни 'bird' (4 символа), длина 64KB» → сервер: «bird + 64KB соседней памяти (может включать ключи, сессии)»
Особых привилегий не требовалось; повторяя это, можно было собирать фрагменты памяти понемногу. Крошечный баг в самом фундаментальном из слоёв пошатнул доверие к мировому трафику.
Ужас «бесследной» утечки
Heartbleed почти не оставлял следов в обычных логах доступа, поэтому «утекло ли» и «что утекло» было трудно утверждать. В случае сомнений действуйте по худшему сценарию.
Хронология
2014-04-07
Уязвимость раскрыта, исправленный OpenSSL выходит в тот же день.сразу после
Серверы по всему миру массово патчатся; широта влияния вызывает тревогу.впоследствии
Многие сервисы отзывают и перевыпускают сертификаты «считая, что ключ утёк», и просят пользователей сменить пароли.
Почему «один лишь патч» — не конец
Если приватный ключ мог утечь, то даже после патча старый ключ всё ещё действителен. Поэтому реагирование состоит из двух частей — закрыть дыру (патч) плюс ротировать активы так, будто они утекли (ключи, сертификаты, секреты).
Недостаточное реагирование
- Обновить OpenSSL и считать «исправлено»
- Ротировать только тот один секрет, чьё злоупотребление подтверждено
- Продолжать использовать тот же сертификат
Правильное реагирование
- Обновить и отозвать/перевыпустить сертификаты (перегенерировать приватный ключ)
- Ротировать каждый секрет, ключ и пароль, которые держит сервер
- Предложить пользователям сменить пароли
Уроки, которые всё ещё применимы
Действуйте так, будто утекло всё
Ротируйте каждый секрет, ключ и пароль — не только тот, что подтверждён. При бесследной утечке предполагайте худшее.
Отзывайте и перевыпускайте сертификаты
Если приватный ключ мог утечь, перестройте и сертификат. Пока вы не ротируете ключ, прошлая утечка остаётся живой.
Мониторьте и фундаментальное ПО
Отслеживайте CVE в «фундаментах» вроде OpenSSL, а не только в своём приложении. Чем глубже слой, тем шире влияние.
Цените безопасность работы с памятью
Баги «читает больше запрошенного» структурно сокращаются при memory-safe дизайне и языках. Учитывайте это в том, на чём строите.
Читать дальше
- Глоссарий: Что такое CVE
- Инцидент: Когда .env раскрыл все секреты
- Основы: Защита секретов, для начинающих
FAQ
QЧто могло утечь в Heartbleed?
Память сервера — в худшем случае приватный ключ TLS, содержимое сессий и данные входа. И это почти не оставляло следов, поэтому «сколько утекло» было трудно определить постфактум.
QПочему он «возвращал больше запрошенного»?
В обмене keep-alive (heartbeat) сервер доверял длине, заявленной партнёром, вместо того чтобы её проверить. Отправьте несколько байт, но заявите «верни 64KB» — и сервер читал за пределами ваших данных в соседнюю память и возвращал её. Доверие к вводу (длине) и было дырой.
QЧто было важнее всего в реагировании?
После патча — действовать так, будто утекло всё: отзыв и перевыпуск TLS-сертификатов и ротация каждого секрета и пароля, которые держал сервер. Одного патча приложения было недостаточно.