Elf bytes zorgen ervoor dat een ongepatchte OpenSSL-server tot 131 KB geheugen reserveert voor een bericht dat nooit aankomt. Op de glibc-systemen die Okta heeft getest, is dat geheugen verdwenen totdat het proces opnieuw wordt opgestart.
OpenSSL heeft de HolleByte opgelost in juni zonder CVE, zonder advies en zonder wijzigingslogboek dat ernaar verwijst. Okta’s Red Team, dat de denial-of-service-bug rapporteerde en deze een naam gaf, publiceerde de details donderdag.
De vaste releases zijn OpenSSL 4.0.1, 3.6.3, 3.5.7, 3.4.6 en 3.0.21, allemaal gedateerd op 9 juni. Elke release op die branches vóór de vaste versies heeft deze. Niets in een normale patchpijplijn zal u hierop wijzen: er is geen identificatiecode waarmee een scanner kan worden vergeleken en er is geen advies om te lezen.
Het probleem is dat OpenSSL het woord van de aanvaller geloofde. Elk TLS-handshakebericht heeft een header van 4 bytes, waarvan drie bytes aangeven hoe lang de body zal zijn. Oudere versies vergrootten de ontvangstbuffer tot de aangegeven grootte op het moment dat de header landde, voordat een enkele byte van de body verscheen, en voordat de eigen controles van de handshake werden uitgevoerd.
Voor een inkomende ClientHello is het plafond 131 KB. Dan blokkeert de werkdraad, wachtend op een lichaam dat nooit komt. Geen authenticatie, geen sessie, geen sleuteluitwisseling.
De herinnering komt niet terug
Op zichzelf is dat een aanval van verbindingsuitputting, en die zijn zo oud als Slowloris. Wat HollowByte doet blijven hangen is glibc. Wanneer de aanvaller de verbinding verbreekt, maakt OpenSSL de buffer vrij, maar glibc houdt kleine en middelgrote stukjes vast voor hergebruik in plaats van ze terug te sturen naar de kernel.
Bij elke verbinding varieert de geclaimde omvang van de aanval, en in Okta’s tests was dat voldoende om te voorkomen dat de allocator hergebruikte wat hij had vrijgemaakt. De hoop fragmenteert, de grootte van de bewoners stijgt en blijft beklommen lang nadat de aanvaller weg is.
Bij de NGINX-tests van Okta werd een server van 1 GB door OOM uitgeschakeld, terwijl 547 MB geheugen in fragmenten bevroren was. Op een server van 16 GB sloot HollowByte 25% van het systeemgeheugen op zonder ooit het verbindingsplafond te overschrijden. Daarom zegt het Red Team dat “standaard verbindingsbeperkende verdedigingen dit niet zullen stoppen”.
Deze cijfers zijn van Okta zelf en er is geen exploitcode bij gepubliceerd. The Hacker News vond vanaf 18 juli geen openbare proof-of-concept-repository op GitHub.
OpenSSL besloot dat dit geen kwetsbaarheid was
Het pull-verzoek van Matt Caswell, die de patch heeft geschreven, zegt het duidelijk: het beveiligingsteam heeft ervoor gekozen om “dit alleen te behandelen als een ‘bug or hardening’-oplossing”. Het eigen beveiligingsbeleid van OpenSSL definieert vier ernstniveaus, van kritiek tot laag, en ‘bug of verharding’ hoort daar niet bij.
Zelfs een laag probleem levert een CVE, een changelog-opmerking en een vermelding op de kwetsbaarhedenpagina op. HollowByte heeft geen van de drie. The Hacker News vond geen melding van de oplossing in de release-opmerkingen of in alle 23 vermeldingen van OpenSSL’s 4.0.1 changelog.
OpenSSL heeft niet gezegd waarom. Voor hen is het volgende het geval: 131 KB per verbinding is klein, elke TLS-server wijst geheugen per verbinding toe en een begrensde toewijzing is geen kwetsbaarheid. Okta’s antwoord is dat de herinnering nooit meer terugkomt.
The Hacker News heeft OpenSSL gevraagd waarom HollowByte onder Low werd beoordeeld en of de oplossing de takken met uitgebreide ondersteuning 1.1.1 en 1.0.2 bereikte. Het heeft Okta ook gevraagd of de fragmentatie andere allocators dan glibc overleeft. Dit verhaal wordt bij elke reactie bijgewerkt.
De lijn van het project is fijner dan het lijkt. In januari heeft OpenSSL CVE-2025-66199, met de beoordeling Laag, toegewezen aan een bug in de compressie van TLS 1.3-certificaten, waarbij een peer-aangeleverde lengte vóór validatie een heapbuffer groeide, ter waarde van ongeveer 22 MiB per verbinding.
Daarvoor waren vier dingen nodig: certificaatcompressie gecompileerd, een compressie-algoritme beschikbaar, over de extensie onderhandeld en, op servers, clientcertificaten aangevraagd. HollowByte heeft er geen van nodig.
In dezelfde release van 9 juni werd CVE-2026-34183, met de classificatie Moderate, toegewezen aan onbegrensde geheugengroei in de QUIC PATH_CHALLENGE-handler. Beide zijn DoS met geheugenuitputting. Beiden kregen nummers.
De release sloot ook 18 CVE’s af, waaronder een High-severity use-after-free in PKCS7_verify(), dus iedereen die een van deze upstream-builds uitvoert, heeft de oplossing zonder dat dit wordt verteld.
Stroomafwaarts is het nog erger. De gedocumenteerde standaard van Red Hat is om de versie te backporteren in plaats van te verplaatsen, dus een gepatcht pakket rapporteert nog steeds de versie waaruit het is gebouwd. Wat dit normaal gesproken oplost, is de advies- en de OVAL-feed, beide gekoppeld aan CVE-namen. Er is hier geen CVE om op in te spelen.
Dan blijft het pakketwijzigingslogboek of de onderhouder over: vraag of ze zich hebben gebaseerd op de release van 9 juni of de patch hebben overgenomen, namelijk pull-request 30792 voor master en 4.0, 30793 voor 3.6, 3.5 en 3.4, en 30794 voor 3.0.
Als u OpenSSL zelf bouwt, upgrade dan naar de genoemde release en start opnieuw op, ongeacht waar de oude is geladen.
De oplossing heeft alleen betrekking op TLS. Caswell schreef over het pull-verzoek dat DTLS met rust werd gelaten omdat het veel invasiever zou zijn geweest als het op de juiste manier zou worden uitgevoerd, en dat het project besloot zich er voorlopig niet mee bezig te houden. The Hacker News vergeleek de broncode van OpenSSL met de tags 3.6.2 en 3.6.3 en ontdekte dat het DTLS-handshakebestand byte-identiek was voor de oplossing. In 4.0.1, de nieuwste release, wordt de buffer van dat pad nog steeds aangepast aan de lengte die de peer declareert.
OpenSSL heeft dat pad niet geclassificeerd en heeft zich ook niet geëngageerd om het te repareren. De release notes, de changelog en de kwetsbaarhedenpagina zeggen er niets over. Het pull-verzoek doet dat wel.