NCSC waarschuwt voor ernstige remote code execution-bug in Java Spring Framework

Verschillende beveiligingsbedrijven en overheidsinstanties waarschuwen voor een ernstig lek in het Java Spring Framework. Die bug, met de bijnaam Spring4Shell, maakt het mogelijk om op afstand code uit te voeren op systemen. Misschien vinden er al aanvallen plaats.

De waarschuwing komt onder andere van beveiligingsbedrijf Rapid7, maar ook het Nederlandse Digital Trust Center en het NCSC waarschuwen voor de kwetsbaarheid. Die heeft inmiddels de bijnaam Spring4Shell gekregen. De kwetsbaarheid zit in het Spring Core Framework van Java. Dat framework wordt gemaakt door Spring.io, dat onderdeel is van VMware. Spring Core is ingebakken in veel Java-software. Het NCSC heeft de bug aangemerkt met de classificatie High/High.

De kwetsbaarheid maakt het mogelijk om een remote code execution uit te voeren zonder dat daar authenticatie voor nodig is. De bug zit in functies die @RequestMapping gebruiken. Aanvallers kunnen vanaf een afstand een webshell opzetten in een rootdirectory waar de software op draait. Volgens Rapid7 zit de bug niet in alle Java-versies; het bedrijf zegt hem succesvol te kunnen uitbuiten op OpenJDK 11.0.14.1, maar niet op 1.8.0_312. Spring.io zegt in een blogpost dat alleen gebruikers van JDK 9 of hoger kwetsbaar zijn. Ook zijn alleen gebruikers kwetsbaar die Apache Tomcat op een server hebben draaien. Het bedrijf waarschuwt dat er verschillende manieren kunnen zijn om de kwetsbaarheid uit te voeren.

Ontwikkelaar Spring.io heeft inmiddels een update beschikbaar gesteld die het lek kan dichten. Die kwam donderdagmiddag uit. De bug is in Spring Framework-versies 5.3.18 en 5.2.20 verholpen. Aanvankelijk was er onduidelijkheid over de bug, omdat onder andere het NCSC waarschuwde voor een andere kwetsbaarheid in de Spring Cloud Function van Java. Die bug kreeg de code CVE-2022-22963 mee, maar heeft volgens beveiligingsbedrijven en -instanties niets te maken met Spring4Shell, dat vooralsnog geen CVE-classificatie heeft gekregen.

Rapid7 zegt dat het de bug op het spoor kwam nadat een beveiligingsonderzoeker een proof-of-conceptexploit had uitgebracht waarbij hij code via Spring Framework kon uitvoeren, maar details over die kwetsbaarheid waren niet bekend. Rapid7 zegt nu dat het die kwetsbaarheid heeft achterhaald. Het bedrijf waarschuwt dan ook dat het proof-of-concept inmiddels al actief zou kunnen worden ingezet, al zijn daar nog geen concrete aanwijzingen voor.

Door Tijs Hofmans

Nieuwscoördinator

31-03-2022 • 15:35

44

Submitter: SL3Y4R

Reacties (44)

44
43
26
2
1
10
Wijzig sortering
Wat ik ervan begrijp is dat Spring toestaat om de classLoader van je applicatie te benaderen via een query parameter. Dus in plaats van dat je /search?name= doet, doet je in dit geval /search?class.module.classLoader=value. Nu is de kwetsbaarheid dat je doordat je bij je classLoader kan, je eigenlijk bij alles kan wat in je classLoader staat (1).

In de exploit gebruiken ze dit om de logging settings van Tomcat aan te passen (welke dit toestaat) (2). Tomcat wordt zo geconfigureerd dat het een nieuwe 'log file' wegschrijft met een specifiek 'pattern' bij het benaderen. De 'logfile' komt te staan in webapps/ROOT/shell.jsp, met een pattern <% /* payload */ %>. Alles binnen de <% %> wordt bij een JSP (3) door de java compiler en runtime gehaald.
Het interessante deel uit de payload in deze exploit is vervolgens:

Runtime.getRuntime().exec(request.getParameter("cmd"))

wat een shell command uitvoert.
De user (en rechten) waarmee de shell wordt uitgevoerd zijn dezelfde als die van de user die de java applicatie gestart heeft.

Spring4Shell bestaat dus uit meerdere stappen/exploits:
(1) classLoader access. Dit is nieuw, en biedt toegang to alle classes in je applicatie.
(2) tomcat wiens configuratie live aan te passen is. Dit zou ook niet zomaar moeten kunnen, en dan al helemaal niet om je 'logfile' in een directory in je online webapp/workdir te kunnen zetten.
(3) uitvoeren van JSP. Dit is standaard functionaliteit van Java.

De reden dat dit pas vanaf Java 9 werkt, is dat spring al jaren eerder een expliciete uitzondering had gemaakt om ?class.classLoader niet toe te staan. Maar in Java 9 is met het modules systeem een andere route bij gekomen via ?class.module.classLoader.
Gebruik je geen Tomcat, dan kan je de Tomcat 'logging' configuratie aanpassen om in je webapp/workdir te schrijven.
Gebruik je geen JSP, dan heb je geen last van het compileren en runnen van 'nieuwe' code zoals JSPs doen.

Maar dat is enkel deze exploit! Het enge hierbij is dat je als aanvaller bij alle classes kan waar je classLoader bij kan. Spring4Shell is maar één voorbeeld, door een aanpassing in Tomcat te doen. Maar er zijn vast andere delen van classes die gevoelige informatie hebben of prijs kunnen geven (denk aan een getSecret(), of een setSecure(false) of een setPassword(123456)).

Als voorbeeld voor niet technici: Denk aan The Matrix, waar ze op een gegeven moment de achterdeuren van matrix door kunnen stappen. En dat Neo de groene code kan zien en de wereld om zich heen kan manipuleren. Je Spring applicatie code is de wereld, de classLoader biedt toegang tot de achterdeuren, groene code en mutaties. De exploit maakt jou Neo.
Deze kwestbaarheid is toch alleen te misbruiken als je een webserver hebt die vanuit de cloud te benader is?
Een server in het LAN welke een intranet website geeft is toch niet kwetsbaar? Althans niet voor de buiten wereld. Tenzij men van buitenaf een VPN verbinding weet te maken.
Voor zover ik t begrijp kun je via de Spring WebDataBinder binden aan properties die gerelateerd zijn aan het classloading mechanisme.

Dat was al ooit gepatched maar met een nieuwer classloading mechanisme sinds Java9 (want modules) is dat via andere routes opnieuw mogelijk geworden (dit is dus gepatched vanaf spring framework 5.3.28)

De hotfix is t maken van een Controller-advice of filter die voor alle requests bepaalde properties negeert (dingen met class enzo).

Het specifieke classloading mechanisme wat misbruikt werd in deze CVE is overigens alleen beschikbaar in de oude war-file deployment manier in een tomcat server
In tegenstelling tot wat er bij de advisory staat, hadden wij een iets grotere aanpassing in de pom nodig:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.18</version>
</dependency>

[Reactie gewijzigd door codekloppertje op 22 juli 2024 18:15]

Staat er gewoon in toch?
Spring Framework versions 5.3.18 and 5.2.20, which address the vulnerability, are now available.
Met die pom aanpassing stel je gewoon 5.3.18 als versie in, waar je voorheen een oudere versie had staan.
Er zijn ook nieuwe versies uitgekomen van Spring Boot (2.5.12 en 2.6.6), mocht je dit gebruiken.
Here we go again....

Kan iemand met verstand van zaken de impact van deze bug vergelijken met log4j?
Veel kleinere impact: het is een front-end framework dus veel zichtbaarder en lijkt niet van toepassing op oudere Java versies (moet nog blijken) waardoor het op dit moment niet speelt voor veel embedded/verborgen meuk die vaak ook nog op oudere Java versies zit.
Totaal niet mee eens

Afgezien van het feit dat je Spring niet echt een front-end-framework kan noemen (het draait vooral op servers) is er nog meer mis:

Het gaat inderdaad vooral om 'nieuwere' java versies. Maar JDK9 is ook niet echt heel nieuw te noemen.
Users of JDK 9 should update to JDK 10 between its release in March 2018 and the next planned Critical Update Release in April 2018.
Dus mensen die al 4 jaar geen updates hebben doorgevoerd zullen 'veilig' zijn voor deze bug, maar die hebben dan waarschijnlijk wel wat andere steken laten vallen.
Aan de andere kant; Java 8 heeft nog support tot 2030, dus het is niet alsof je dan op unsupported software draait.
Goed gevonden, daar had ik inderdaad niet aan gedacht.

Let wel op dat dit alleen geldt voor "Extended Support" (waar je voor moet betalen). Als je nu zonder na te denken Java 8 wil gaan downloaden krijg je dit te zien:
WARNING: These older versions of the JRE and JDK are provided to help developers debug issues in older systems. They are not updated with the latest security patches and are not recommended for use in production.
Als je genoeg geld neerlegt kan je zelfs 'levenslang' support van Oracle krijgen ;)

Edit: OpenJDK 1.8.0_312 (waar in dit artikel ook over gesproken wordt) heeft support tot 2026, dus je hebt eigenlijk ook wel gelijk :). Ik ben niet 100% thuis in de verschillende java versies

[Reactie gewijzigd door svane op 22 juli 2024 18:15]

Oracle JDK is al sinds 2020 alleen voor betalende bedrijven en thuisgebruikers. Wil je niet betalen maar er wel commerciele activiteiten mee ontplooien dan word je doorverwezen naar de OpenJDK versies (waar Oracle ook een hele grote vinger in de pap heeft, maar waar geen betaalde support op zit) zoals AdoptJDK (nu Eclipse Adoptium), OpenJDK zelf, of iets als Azul, of zelfs Microsoft die nu een OpenJDK bakt.

In alle gevallen zijn Java 8, 11 en 17 Long Term Supported, en alle tussenliggende versies zijn gewoonlijk maar een maand of 6 supported, tot de volgende uit is. Gezien de stap van 8 naar 11 groot is, wordt 8 extra lang gesupport (en wordt dat langzaam een Python 2, niet dood te krijgen, maar ook niet echt levend meer).
Interessant, bedankt! Dankzij alle verschillende varianten (OpenJDK / AdoptJDK / etc.) en versienummers was ik een beetje de weg kwijt. :)
Om mij heen zie ik meer bedrijven met OpenJDK 1.8.0_312 (en Spring). Gelukkig voor hen, niks aan de hand.
OM het moeilijk te maken, wat daar staat is alleen voor de RedHat variant/build van de OpenJDK, Alle vendors die zelf de OpenJDK compilen kunnen hun eigen support beloven. De OpenJDK (deze staan op https://jdk.java.net/ en wordt voglens mij door Oracle zelf gecompiled) worden al niet meer uitgeleverd. De Oracle JDK heeft nog wel paid support.
De openJDK wordt door veel vendors gebuild, zie hier een lijst: https://en.wikipedia.org/wiki/OpenJDK#OpenJDK_builds
De changes van Oracle worden wel genoemd als paid support, maar houdt eigenlijk in dat je vanaf jdk1.8.202 moet betalen per seat.
Dit is voor veel partijen een reden om over te stappen op openjdk.
het is een front-end framework
Nee, Spring is geen front-end framework. Het is een heel groot en zeer veel gebruikt framework voor Java webapplicaties en webservices. Hiermee schrijf je je back-end (server-side) code en niet het front-end.

Of bedoelde je "het is geen front-end framework"? (Overigens is Log4J ook geen front-end framework). Ik snap ook niet wat je dan bedoelt met "veel zichtbaarder".

[Reactie gewijzigd door jj71 op 22 juli 2024 18:15]

Hangt er vanaf wat je definitie van "Front-End" is. Als je alleen JavaScript frameworks daaronder rekent, ben je denk ik wel erg gelimiteerd in je definitie. Spring heeft bijv. Spring MVC, wat specifiek bedoelt is om als user facing technologie te dienen en HTML en dergelijke uit te spugen. Dus dat onderdeel is IMO gewoon een Java frond-end framework, net als Apache Tapestry, Apache Wicket of Apache Struts.

Spring is natuurlijk veel groter dan Spring MVC, maar er zijn niet heel veel bedrijven die volgens mij Spring inzetten zonder MVC, of Spring Boot, en is dus Spring "front-end" framework noemen niet geheel onterecht.
maar er zijn niet heel veel bedrijven die volgens mij Spring inzetten zonder MVC, of Spring Boot, en is dus Spring "front-end" framework noemen niet geheel onterecht.
Spring wordt aardig veel gebruikt zonder Spring MVC, naar mijn idee. Spring is in zijn kern ook ontstaan als dependency injection framework, zo'n 20 jaar geleden, toen Spring MVC nog niet bestond. En bouwde al voor Spring MVC, goede bekendheid op.
Het klopt dat Spring MVC en Boot veel gebruikt worden, en daarmee veel als front-end voorkomen, maar ook in de backend wordt Spring naar mijn idee veel gebruikt. Bijvoorbeeld voor batch processing, database interactie (Spring Data), messaging, cloud, security, aop, etc. Bedrijven als Netflix maken ook flink gebruik van Spring in de backend. Ook Wicket (;)) kan prima samen met Spring zonder Spring MVC.

[Reactie gewijzigd door Cyb op 22 juli 2024 18:15]

Spring is geen front-end framework, maar een framework dat veel van het mundane werk voor je doet als je een back-end opzet in Java.
Ik ken spring vrij aardig en dit zit in de rest endpoints van spring. Dat is redelijk frontend. Het is inderdaad niet in de browser maar om je definitie van front-end te beperken tot HTML krassen. Een rest endpoints is redelijk frontend wat mij betreft en dus zichtbaar.
en rest endpoints is redelijk frontend wat mij betreft en dus zichtbaar.
Die rest endpoints zijn juist iets dat door de meesten als 'backend' gezien wordt. Er valt wel iets voor te zeggen om dit onder frontend te scharen, maar in de praktijk werkt dit alleen maar verwarring op.

Wiki:
, the client is usually considered the frontend and the server is usually considered the backend, even when some presentation work is actually done on the server itself.
Dus ondanks dat Spring een mooie JSON (of html) uitspuugt, wordt dit vaak nog steeds als backend gezien.
A rule of thumb is that the client-side (or "frontend") is any component manipulated by the user. The server-side (or "backend") code usually resides on the server, often far removed physically from the user.
Bij een situatie waar een React-site via een api praat met een Spring-applicatie, daar zouden toch heel veel mensen zeggen dat de spring-applicatie het backend is.

Wanneer spring zich ook met de javascript/css/html gaat bemoeien, dan wordt die grens inderdaad vager.

Je originele punt was ook:
het is een front-end framework dus veel zichtbaarder
De eindgebruiker gaat meestal niet direct met de endpoints praten, en ziet deze ook niet zelf. In de proof-of-concept maakt de exploit ook een nieuwe route/url aan. Deze is voor gebruikers die niet naar deze url gaan onmogelijk te zien.
Hmm. Ik kom nog uit de web 1.0 tijd en static HTML front-end noemen ging toen al te ver, vandaar dat de web-layer op server ook al front-end genoemd werd. Qua zichtbaarheid bedoel ik:
1) Je kunt het poortscannen (lastiger met log4j)
2) Als er wijzigingen zijn aan de applicatie dan zal dat veelal aan de 'voorkant' gebeuren. Upgraden/aanpassen logging stack doe je 1x aan het begin van je project je denkt er niet meer over na. Een rest-api aanpassing zal veel vaker gebeuren. Tevens zijn deze vaak exposed richting internet (als er bijv. een JS applicatie in de browser mee moet babbelen) dus is er meer aandacht voor eventuele issues en een upgrade pad is eenvoudiger. Log4j zat bijv. ook in command-line tools die vanuit een verborgen cron-job eens per maand een aantal files overzet. Draait al 15 jaar zonder gezeik en de bouwer is met pensioen. Dat verwacht ik niet met een rest-endpoint.

Of je iets front of backend noemt is verder een definitie kwestie en afhankelijk van waarvan je kijkt. Het eigenlijk ook zuiverder om te spreken over de view-layer (en daaronder de service-layer en daaronder de database layer). HTML+JS in de browser is dan de presentation layer. Als je voor een 100% JS/HTML architectuur kiest dan zitten presentation/view en service layer in de browser en doe je je data via REST en zit alleen de data-layer op de server. Die exposed dan de SQL server data maar heeft daar zelf een view/service/data layer voor nodig. Vandaar dat ik altijd de wenkbrauwen optrek bij full-stack developers. Welke stack ben je dan full in? ;-)
uhm nee en ook niet in de tijd van web 1.0. Het verschil zit hem in wie de code uitvoert. Gebeurt dat aan de kant van de gebruiker (in de client, oftewel de browser? -> frontend, anders -> backend). Maakt verder niet uit welke taal je daarvoor gebruikt. Geserveerde HTML wordt gerendered door de browser, dus frontend, idem voor CSS. Javascript? Hangt ervan af, elke taal in een script tag wordt afgehandeld door de browser, maar veel van die talen kunnen ook aan de kant van de server worden gebruikt. Serverside rendering? Gebeurt niet aan de klant van de gebruiker, dus backend, maar het resultaat, html, wordt gerendered door de browser, dus frontend. Rest API, de data wordt gegenereerd door de server, dus backend, data inlezen gebeurt in een script in de browser, dus frontend. Een database? Afhankelijk op die op een server draait backend, maar moderne browsers ondersteunen ook IndexedDB, dus dat is frontend. Geen kwestie van definitie. https://en.wikipedia.org/wiki/Frontend_and_backend

Sping Framework wordt niet aan de frontend gebruikt, want - wellicht afgezien van een experiment om het in een applet aan de praat te krijgen - het is een framework voor serverside taken, dus backend.
Hmm. Het wordt een beetje een definitie kwestie en die is met de komst van Javascript in de browser flink verschoven. Ik snap de redenering die je opzet, alleen als je die lijn doorzet is het uiteindelijk de monitor wat het front-end is want die toont de gerenderde pixels aan de gebruiker. De browser bepaalt alleen waar de monitor de pixels laat zien :) Maar zoals altijd in dit soort discussies is het maar net waar je vandaan komt: https://www.ibm.com/docs/...presentation-layer-spring hier is de presentation layer (uit jouw Wikipedia link) JSF/Struts/Spring MVC wat in jouw definitie dan weer onder backend valt. En in Web 1.0 hadden we alleen statische HTML en geen fancy-smancy JS.
De monitor geeft pixels weer zoals je zegt en voert dus niet de code uit. En inderdaad, de presentation layer of de view in bijvoorbeeld mvc dat op een server wordt uitgevoerd is backend. Zet de data van het ene formaat om naar het andere, maar daar komt op dat moment de gebruiker niet bij kijken om die code uit te voeren.

En java script is al sinds 1995 in gebruik, en 2.0 is een term uit de 2000's. En die statische html kon al veel eerder ook door een backend worden gegenereerd en hoefde niet statisch te zijn. Sorry, je kunt het een definitiekwestie blijven noemen, maar al deze dingen zijn gedefinieerd. Voornaamste punt in deze discussie is dat spring iig niet aan de kant van de gebruiker wordt uitgevoerd

[Reactie gewijzigd door jurriaan op 22 juli 2024 18:15]

Spring een front-end framework?
Spring is een backend framework. Wordt gebruikt voor webservices en draait volledig serverside
De impact van deze bug is iets kleiner dan die van Log4J, dat als asbest werkelijk bijna overal in zat. Dit betreft alleen Spring-applicaties, waarbij randzaken als de jdk en de Tomcat-versie ook relevant kunnen zijn. De aanvalsvector is dus iets specifieker.

Op het werk hebben we geconstateerd dat Tomcat vulnerable is, maar embedded Tomcat niet. Dit heeft vermoedelijk te maken met het verschil aan permissies tussen die twee, heb ik begrepen. In de exploitcode moet een bestand worden weggeschreven op het bestandssysteem waarmee later code moet kunnen worden uitgevoerd. Overigens constateerden wij dat het weglaten van @RequestMapping geen verschil maakte.

[Reactie gewijzigd door Ossebol op 22 juli 2024 18:15]

"De impact van deze bug is iets kleiner dan die van Log4J, dat als asbest werkelijk bijna overal in zat."

Mooie uitdrukking en zeker waar :)
Dat embedded Tomcat niet vulnerable is staat bijv. ook in https://portswigger.net/d...ew-zero-day-vulnerability. Dit scheelt een hoop want Spring Boot draait (normaal gezien?) met embedded Tomcat. Al lijken ze wel bang te zijn dat vergelijkbare exploits evt. mogelijk zijn, dus updaten is sowieso wel goed.
Spring is een framework dat erg veel in de Java enterprise wereld wordt gebruikt.
Indien je systeem aan de "impacted" criteria voldoet, is remote code execution mogelijk. Die criteria zijn vrij algemeen, en niet bijzonder, waardoor relatief veel systemen vatbaar kunnen zijn, met potentieel grote gevolgen voor die systemen.

Een benaderbaar systeem dat kwetsbaar is voor Spring4Shell, is gemakkelijker te exploiten dan een benaderbaar systeem dat gevoelig is voor de beruchte Log4Shell. Bij Log4Shell moet de hacker namelijk eerst nog brute force proberen Log4J te triggeren, terwijl dat bij Spring4Shell niet hoeft: je kan meteen exploiten, en je hoeft verder weinig infrastructuur te regelen.
Een verschil met Log4Shell is wel dat het met Log4Shell mogelijk is om systemen aan te vallen die van buiten niet benaderbaar zijn, en bij Log4Shell kan er sprake zijn van groot vertragingseffect. (Hacker valt aan, en moet daarna een onbeperkte tijd wachten voordat het getroffen systeem automatisch contact opneemt met een systeem van de hacker.)
Deze zin klopt niet: 'De kwetsbaarheid zit in het Spring Core Framework van Java'. Spring is niet van Java. Het is geschreven in Java maar het maakt geen deel uit van de Java SDK of JRE.
Juist: de zinsnede zou geschreven moeten zijn "Spring Core Framework voor Java" (er is ook een spring.net iirc).
Blij dat wij op Java 8 draaien en voor nu nog niet in allerijl alles hoeven te patchen. Ik ben net bijgekomen van alle patch rondes van Log4Shell… ;)

[Reactie gewijzigd door Sand0rf op 22 juli 2024 18:15]

Spring Boot versie 2.6.6 is inmiddels beschikbaar. Hierin is het probleem verholpen.
Die bug, met de bijnaam Spring4Shell
Erg jammer dat iemand bedacht heeft om deze naam voor deze bug te gebruiken.

Er is namelijk ook een subproject van het Spring Framework genaamd Spring Shell, die totaal niets met dit securityprobleem te maken heeft.

Dus de naam "Spring4Shell" is erg verwarrend. Bovendien zou de "4" in deze naam ook nog eens mensen kunnen laten denken dat het alleen over versie 4.x van het Spring Framework gaat, wat niet het geval is.
De naam is een variatie op Log4shell, een andere, enorm grote kwetsbaarheid van een paar maanden terug.

Het is vooral stuitend dat er een dergelijke naam aangegeven wordt, nog voordat er een CVE nummer en impactscore bekend is, terwijl de kwetsbaarheid niet te vergelijken is met Log4Shell en ook veel minder impact lijkt te hebben.
Kijk, dat is nog eens uitleg. 👍
Is er al iemand die een kwetsbare (commerciële) applicatie gevonden heeft waarbij de PoC bij standaard installatie aangeeft dat deze vulnerable is?

Op dit item kan niet meer gereageerd worden.