В OpenSSL раскрыли уязвимость, получившую имя HollowByte. Она позволяет удалённому неаутентифицированному атакующему вызвать отказ в обслуживании (DoS) — причём вредоносный пакет может быть размером всего в 11 байт. Нашла проблему красная команда Okta, а корень её — в том, как OpenSSL заранее выделяет память во время TLS-рукопожатия.
Как это работает
OpenSSL резервирует приёмный буфер, ориентируясь на длину сообщения, которую атакующий сам объявляет в записи ClientHello, — ещё до того, как реальные данные придут. Цепочка выделения выглядит так: «чтение заголовка → grow_init_buf() → OPENSSL_clear_realloc() → malloc(размер_от_атакующего)».
Одним хитро сформированным пакетом можно заставить malloc() выделить до 131 КБ — исключительно на основании заявленной атакующим длины. При этом рабочие потоки зависают в бесконечном ожидании данных, которые так и не приходят.
Почему память не возвращается
Когда атакующие соединения обрываются, glibc не отдаёт освобождённые блоки обратно операционной системе, а придерживает их. Пуская волны соединений случайного размера, атакующий мешает повторному использованию памяти: объём резидентной памяти сервера (RSS) растёт безвозвратно даже после отключения клиентов. Единственное лекарство — перезапуск процесса.
Как это выглядит на практике
Тесты на непропатченном OpenSSL с NGINX показали:
- 1 ГБ ОЗУ: сервер словил OOM-kill, накопив 547 МБ фрагментированной памяти;
- 16 ГБ ОЗУ: атака съела 25% всей памяти системы, обойдя стандартную защиту по числу соединений.
Кого касается
Уязвимость затрагивает веб-серверы (Apache, NGINX), среды выполнения языков (Node.js, Python, Ruby, PHP) и базы данных (MySQL, PostgreSQL).
Исправление
OpenSSL закрыла проблему через постепенный рост буфера — пулл-реквесты #30792, #30793 и #30794. Теперь буфер расширяется не по заявленной в заголовке длине, а только по мере реального поступления байтов.
Исправленные версии: OpenSSL 4.0.1, а также бэкпорты в 3.6.3, 3.5.7, 3.4.6 и 3.0.21.
Любопытная деталь: OpenSSL классифицировала это как «улучшение защиты» (hardening improvement), а не завела формальный CVE, — та же практика применялась и к другим недавним DoS-проблемам без громкого номера.