Для атаки на сервер с OpenSSL в случае HollowByte хватает 11 байт. Эта уязвимость OpenSSL не крадет данные и не исполняет код, но умеет делать другую неприятную вещь: раздувать память процесса до состояния, когда сервис начинает задыхаться, а иногда и падает.
О проблеме, как пишет BleepingComputer, рассказала Red Team компании Okta, а разработчики OpenSSL уже внесли исправление и откатили его в несколько поддерживаемых веток. Для русскоязычных команд это история не про академическую криптографию, а про банальную эксплуатацию продакшена: OpenSSL сидит почти везде, от NGINX и Apache до рантаймов Node.js, Python, Ruby и PHP, а также в MySQL и PostgreSQL.
Механика у HollowByte неприятно простая. Во время TLS-рукопожатия каждое сообщение содержит 4-байтовый заголовок, внутри которого есть трехбайтовое поле длины. Уязвимые версии OpenSSL сначала доверяют заявленному размеру, выделяют под него память и только потом ждут полезную нагрузку. Проверки на этом этапе не спасают: поток-воркер уже завис в ожидании данных, которые атакующий не собирается присылать.
Практически это выглядит так: злоумышленник открывает TLS-соединение и отправляет 11-байтовый фрагмент, в котором указано, что дальше якобы придет намного больший блок данных. Затем повторяет прием на множестве соединений. На стороне сервера объем реально полученного трафика остается крошечным, а вот выделенная память растет вполне всерьез. Для систем мониторинга это особенно неудобный сценарий: атака может оставаться ниже типичных порогов алертов по полосе пропускания, хотя по факту сервер уже теряет ресурсы.
Отдельная проблема в том, что после закрытия соединения неприятности не всегда заканчиваются. Okta указывает на поведение GNU C Library: glibc не спешит возвращать в операционную систему небольшие и средние выделения памяти, а держит их для повторного использования. В норме это помогает производительности. Но если атакующий запускает волны соединений с рандомизированными размерами, аллокатору сложнее переиспользовать освобожденные куски памяти. Куча фрагментируется, Resident Set Size продолжает расти, и даже после отключения атакующего процесс остается раздутым. Полностью вернуть память в таком сценарии можно только перезапуском сервиса.
На тестах Okta с NGINX эффект оказался вполне прикладным. В средах с небольшим запасом ресурсов память можно быстро исчерпать. На более мощных серверах потери были не катастрофические, но все равно ощутимые: до 25% памяти процесса при том, что трафик атаки оставался ниже порогов, на которых многие команды обычно начинают нервничать. Это делает HollowByte типичной проблемой для инфраструктуры, где много TLS-терминации, но не слишком много запаса на резкие скачки RSS.
Формально речь идет о DoS, а не о компрометации данных, поэтому подобные баги часто получают меньше внимания, чем RCE или утечки. На практике это опасная привычка. Если у компании внешний API, веб-приложение, клиентский портал или критичный внутренний сервис живет за OpenSSL, то уязвимость OpenSSL такого типа бьет по доступности, SLA и репутации. Для B2B-сервисов это быстро превращается из технической детали в разговор с клиентами и руководством: почему сервис не отвечал, почему алерты не сработали раньше и почему для восстановления понадобился рестарт.
Еще один неприятный момент в том, что идентификатор уязвимости проблеме не присвоили. OpenSSL исправил ее тихо и подал как hardening fix, а не как security vulnerability. С инженерной точки зрения это не слишком утешает. Если библиотека массово используется как основа TLS-коммуникаций, а атака возможна без аутентификации и почти без трафика, спор о терминах уже не так важен. Для эксплуатации не нужен доступ к аккаунту, не нужен сложный эксплойт и не нужен заметный объем запросов.
Исправление вошло в OpenSSL 4.0.1, а также было перенесено в версии 3.6.3, 3.5.7, 3.4.6 и 3.0.21. После патча библиотека больше не раздувает буфер по одному лишь обещанию в заголовке и наращивает его только по мере фактического поступления данных. Для инфраструктурных команд это означает довольно прямой список действий: проверить, какая ветка OpenSSL реально стоит в дистрибутиве и контейнерах, не полагаться на название пакета в базовом образе, обновить библиотеку, а затем убедиться, что зависящие сервисы действительно используют исправленную сборку после перезапуска или перекатки.
Здесь важен и организационный вывод. OpenSSL предустановлен почти во всех Linux-дистрибутивах, поэтому проблема редко живет в одном конкретном приложении. Она может сидеть в веб-сервере, в приложении, в прокси, в агенте мониторинга или в старом сервисе, про который вспоминают только в момент инцидента. Если у команды нет точного инвентаря по TLS-библиотекам и зависимостям, HollowByte быстро превращается в упражнение на поиск иголки в стоге CI/CD-артефактов. И это, пожалуй, самая неприятная часть истории: атака занимает 11 байт, а разбор последствий легко растягивается на полдня и несколько команд.
История с HollowByte в очередной раз напоминает, что слабым местом бывает не только логика приложения, но и поведение базовой библиотеки под необычной нагрузкой. Чем больше компаний выносят TLS-терминацию на плотные, экономно настроенные узлы, тем дороже становятся баги, которые не ломают шифрование, а просто заставляют инфраструктуру медленно распухать до отказа.