← Alle artikelen
Node.js

Node2Shell: is uw Node.js-applicatie echt kwetsbaar?

Een fout in de Brotli-decoder van Node.js kan tot code-uitvoering leiden, maar alleen als uw applicatie Brotli-gegevens van buitenaf uitpakt. Wij controleerden de server van Orangeguard: zo bepaalt u in een uur of en waar u risico loopt.

Deze week werd ook PHP getroffen, zie PHP2Shell. Dit artikel gaat over de Node.js-tegenhanger, en over hoe u bepaalt of een kwetsbaarheid in uw situatie echt te misbruiken is.

In het kort

  • Node.js dichtte op 21 oktober CVE-2026-111497, een geheugenfout in de ingebouwde Brotli-decoder die tot code-uitvoering kan leiden.
  • Beveiligingsbedrijf Imperva liet zien dat het werkt, op een officiële Node.js-build. Misbruik in het wild is niet gemeld.
  • U bent alleen kwetsbaar als uw applicatie Brotli-gegevens van buitenaf uitpakt: in binnenkomende verzoeken, of in antwoorden van servers die u zelf benadert.
  • Update in elk geval naar 22.23.4, 24.22.1 of 26.12.1, ook binnen uw containers.

Wat is er aan de hand?

Brotli is een compressiemethode die veel websites gebruiken. Node.js heeft er een eigen decoder voor in node:zlib. Die decoder zag een bepaalde ongeldige invoer aan voor "ik heb meer gegevens nodig" in plaats van "dit klopt niet", en bleef dan gegevens wegschrijven voorbij het einde van een buffer van acht bytes. Volgens Node.js kan dat leiden tot een crash, het lekken van geheugen of code-uitvoering op afstand.

Node.js rekent de fout tot ernst hoog. De oplossing zit in 22.23.4, 24.22.1 en 26.12.1, uitgebracht op 21 oktober. Node.js 20 en ouder worden niet meer ondersteund en krijgen deze oplossing niet. Dezelfde release dicht negen andere kwetsbaarheden, waaronder fouten in de controle van TLS-certificaten.

Imperva noemt de aanval Node2Shell en voerde eigen code uit op het officiële Node.js 24.22.0-image voor Linux arm64, zonder debugger of aangepaste build. Het lukte niet bij elke poging: "execution took multiple attempts", schrijft Imperva. Er is geen misbruik in het wild gemeld.

Wanneer bent u echt kwetsbaar?

Een kwetsbare Node.js-versie is niet automatisch een kwetsbare applicatie. De aanvaller moet Brotli-gegevens aanleveren die uw applicatie uitpakt. Imperva beschrijft twee routes, en benadrukt dat een kale Node.js-webserver een binnenkomend Brotli-verzoek niet vanzelf uitpakt.

Route Voorwaarde Voorbeeld
Binnenkomend verzoek Uw framework pakt Brotli-verzoeken uit Express 5 met body-parser 2, getest door Imperva
Uitgaand verzoek Uw applicatie haalt iets op bij een server die de aanvaller beheert fetch(), dat Brotli-antwoorden automatisch uitpakt

De tweede route wordt vaak vergeten. Denk aan alles waarbij uw applicatie een adres opvraagt dat een gebruiker opgeeft: een linkvoorbeeld, een webhook, een RSS-import, een oEmbed-kaart. Wie dat adres opgeeft, bepaalt wat er terugkomt.

Hoe wij onze eigen server controleerden

Orangeguard draait op Ghost en Umami, allebei Node.js-applicaties in Docker-containers. Toen de melding binnenkwam, hebben we in een klein uur vastgesteld wat het risico was.

1. Welke Node.js draait er echt? Niet op de server zelf, maar in elke container: node -v in de container. Ghost draaide 22.23.2 en Umami 22.23.1, beide vóór de oplossing. Een pakketoverzicht van de server had dit niet laten zien, want Node.js zit in de images.

2. Pakt de applicatie binnenkomende Brotli-verzoeken uit? Ghost gebruikt Express 4 met body-parser 1.20. In de code van body-parser was te zien dat die versie alleen gzip en deflate kent; een verzoek met Content-Encoding: br wordt geweigerd met foutcode 415. De route van Imperva via Express 5 was dus dicht. In Umami vonden we geen code die Brotli uitpakt.

3. Haalt de applicatie zelf iets op? Ja. In Ghost zitten meerdere HTTP-libraries die Brotli-antwoorden automatisch uitpakken, waaronder die voor linkvoorbeelden. Een aanvaller zou Ghost een adres moeten laten ophalen van een server die hij beheert. In onze opzet kan alleen de redactie zo'n link toevoegen, en de beheeromgeving is afgeschermd. Klein risico, maar niet nul.

4. Bijwerken. Binnen twee dagen na de Node.js-release waren er nieuwe officiële images van Ghost en Umami op 22.23.4. Na een back-up hebben we beide bijgewerkt en daarna in de containers gecontroleerd dat node -v 22.23.4 meldde. Ook controleerden we dat de site, de statistieken en de beheeromgeving werkten.

De conclusie: kwetsbare versie, beperkte blootstelling, en toch dezelfde dag bijgewerkt. Een analyse als deze vervangt de update niet. Ze vertelt u alleen hoe snel die moet.

Wat u nu kunt doen

  1. Zoek al uw Node.js-runtimes op, ook binnen containers, in zelfgebouwde images en in programma's die Node.js meeleveren. Controleer de versie in de draaiende omgeving, niet in een pakketlijst.
  2. Update naar 22.23.4, 24.22.1 of 26.12.1. Gebruikt u een officieel image, pull dan de nieuwste versie. Bouwt u zelf images op een Node.js-basisimage, bouw ze dan opnieuw. Applicaties die als losse executable of met een opstartsnapshot zijn gebouwd, moeten ook opnieuw worden gebouwd: daar zit een eigen kopie van Node.js in.
  3. Kijk welke body-parser of welk framework u gebruikt. Bij Express 5 en body-parser 2 loopt u het meeste risico. U kunt het snel testen: een verzoek met Content-Encoding: br en onschuldige inhoud. Antwoordt de applicatie met 415, dan pakt hij geen Brotli uit.
  4. Breng de uitgaande verzoeken in kaart. Waar haalt uw applicatie iets op bij een adres dat een gebruiker kan opgeven? Die plekken verdienen voorrang bij het updaten.
  5. Als u niet direct kunt updaten: weiger verzoeken met Content-Encoding: br op uw proxy of loadbalancer, of zet het uitpakken in body-parser uit. Imperva heeft regels in zijn WAF toegevoegd; dat is een tijdelijke laag, geen oplossing.
  6. Stap over van Node.js 20 en ouder. Die versies krijgen deze oplossing niet.

Bronnen

De Orangeguard nieuwsbrief

Blijf digitaal weerbaar.

Nieuws over cybersecurity en praktische inzichten, rechtstreeks in je inbox.

Meld je aan