In this article
Eine Java-Spring-Boot-API vor fehlerhafter JSONObject-Serialisierung schützen: CVE-2023-5072
Die kürzlich entdeckte CVE-2023-5072, eine kritische Sicherheitslücke im Zusammenhang mit der JSONObject-Serialisierung, hat erhebliche Sicherheitsbedenken für Java-Entwicklerinnen und -Entwickler aufgeworfen, insbesondere für diejenigen, die das Spring-Boot-Framework verwenden.
Diese Out-of-Memory-Sicherheitslücke, die auf einen Fehler in der Art und Weise zurückgeht, wie JSONObject die Serialisierung verarbeitet, kann Java-Anwendungen einer Reihe von Sicherheitsbedrohungen aussetzen.
CVE-2023-5072 stellt ein herausforderndes Szenario dar, in dem die Integrität von Datenstrukturen während der Serialisierung und Deserialisierung beeinträchtigt werden kann. Dies ist besonders kritisch für Anwendungen, die mit Spring Boot entwickelt wurden, das wegen seiner Effizienz und Benutzerfreundlichkeit bei der Entwicklung robuster Java-Anwendungen weit verbreitet ist.
Die Art und die Auswirkungen solcher Sicherheitslücken zu verstehen, ist entscheidend, um die Sicherheit und Zuverlässigkeit von Java-Anwendungen in einer zunehmend komplexen digitalen Landschaft zu gewährleisten.
In diesem Artikel möchten wir das Problem verständlich erläutern. Dazu erstellen wir eine einfache Java-API und stellen praktische Schritte vor, mit denen Sie die Risiken in einer Spring-Boot-API-Umgebung mindern können.
Eine Spring-Boot-Java-API mit der JSONObject-Sicherheitslücke CVE-2023-5072
Um die JSON-Serialisierungssicherheitslücke in JSONObject zu veranschaulichen, erstellen wir einen kleinen Java-API-Server mit Spring Boot und Maven. Er verarbeitet eine POST-Anfrage an /api/todos, parst ein JSON-Objekt mit einem Array von To-do-Elementen und gibt deren Anzahl in der HTTP-Antwort zurück.
Beginnen wir mit einer Schritt-für-Schritt-Anleitung zum Erstellen dieses Projekts.
Schritt 1: Projekt einrichten
1. Ein neues Spring-Boot-Projekt erstellen:
a. Mit Spring Initializr können Sie Ihr Projekt generieren.
b. Wählen Sie Maven als Build-Tool aus.
c. Fügen Sie „Spring Web“ als Abhängigkeit hinzu.
d. Laden Sie das Projekt herunter und entpacken Sie es.

2. Projekt öffnen:
a. Öffnen Sie das Projekt in Ihrer bevorzugten IDE (z. B. IntelliJ IDEA, Eclipse oder VSCode).
b. Vergewissern Sie sich, dass die Datei pom.xml vorhanden ist und die Spring-Boot-Abhängigkeit sowie einen Build-Eintrag für das spring-boot-maven-plugin enthält.
Schritt 2: Java-Abhängigkeiten hinzufügen
Abhängigkeiten in pom.xml verwalten
In einer pom.xml-Datei für Maven, ein beliebtes Java-Build-Tool, werden Abhängigkeiten (externe Bibliotheken oder Module, die Ihr Projekt benötigt) mithilfe einer Kombination aus groupId, artifactId und version angegeben. Zusammen identifizieren diese Elemente eine bestimmte Version einer Bibliothek in den Maven-Repositories eindeutig.
Bearbeiten Sie die pom.xml-Datei und vergewissern Sie sich, dass die Spring-Web-Abhängigkeit vorhanden ist. Fügen Sie die JSONObject-Bibliotheksabhängigkeit hinzu. Falls sie nicht in Spring Boot enthalten ist, können Sie die JSON-Bibliothek von org.json verwenden und diese Abhängigkeit hinzufügen:
xml
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20230618</version>
</dependency>
Sehen wir uns die Bedeutung der einzelnen Teile an und konzentrieren wir uns dabei auf die artifactId:
groupId: Dies ist in der Regel der umgekehrte Domainname der Organisation oder Gruppe, die die Bibliothek erstellt hat. In unserer Beispielanwendung istorg.jsondie groupId. Sie zeigt an, dass die Bibliothek von der Organisation json.org gepflegt wird.
artifactId: Dies ist der Name der eigentlichen Bibliothek oder des Moduls. Darauf beziehen Sie sich normalerweise, wenn Sie über eine Bibliothek sprechen. In unserem Fall lautet die artifactIdjson, d. h. der Name der Bibliothek, die wir hinzufügen, ist einfach „json“. Üblicherweise verweist die artifactId auf die Hauptfunktion oder Identität der Bibliothek.
version: Hiermit wird die konkrete Version der Bibliothek angegeben, die Sie verwenden möchten. Die Version 20230618 in unserem Beispiel ist eine eindeutige Versionskennung für die json-Bibliothek. Die Versionierung ist entscheidend für konsistente Builds, da neuere Bibliotheksversionen Änderungen enthalten können, die nicht mit Ihrem Projekt kompatibel sind.
Die Abhängigkeitsdeklaration in der pom.xml-Datei weist Maven also an, die json-Bibliothek aus der Gruppe org.json, und zwar in Version 20230618, herunterzuladen und in das Projekt einzubinden. Das Build-Tool Maven ruft die Bibliothek automatisch aus einem zentralen Repository ab und stellt sie unserem Projekt zur Verfügung.
Schritt 3: Java-API-Controller erstellen
In diesem Schritt fügen wir dem Projekt eigenen Java-Code hinzu und erstellen eine neue API. Dieser neue API-Endpunkt definiert eine HTTP-POST-Anfrage an den URI /api/todos, der von der Java-Anwendung bereitgestellt wird.
Eine neue Controller-Klasse erstellen:
Navigieren Sie in Ihrem Projekt zu
src/main/java/<your-group-id>/<your-artifact-id>/und erstellen Sie ein neues Verzeichnis namenscontroller/. Wenn Sie den Standardvorgaben von Spring Initializr gefolgt sind, lautet der Pfadsrc/main/java/com/example/demo/controller/DemoApplication.java.Erstellen Sie eine neue Java-Klassendatei namens
TodoController.java.
Controller-Code hinzufügen:
Annotieren Sie die Klasse mit
@RestController.Erstellen Sie eine Methode zur Verarbeitung der POST-Anfrage.
Hier sehen Sie ein vollständiges Beispiel für die Klassendatei TodoController.java:
java
import org.json.JSONObject;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TodoController {
@PostMapping("/api/todos")
public String handleTodo(@RequestBody String todoData) {
JSONObject jsonObject = new JSONObject(todoData);
int count = jsonObject.getJSONArray("todos").length();
return "Count: " + count;
}
}Schritt 4: Server starten
Starten wir den Java-Spring-Boot-API-Server. Dafür gibt es zwei gängige Möglichkeiten:
Starten Sie die Anwendung über die IDE, in der Regel durch Drücken der Taste F5.
Navigieren Sie im Terminal zum Stammverzeichnis des Projekts und führen Sie den Befehl
mvn spring-boot:runaus. Dafür muss Maven in Ihrer Entwicklungsumgebung installiert sein.
Nun können wir den Java-API-Endpunkt testen und eine POST-Anfrage senden. Verwenden Sie ein Tool wie Postman oder cURL, um eine POST-Anfrage an http://localhost:8080/api/todos zu senden. Der Body sollte ein JSON-String sein, zum Beispiel: {"todos": ["Task 1", "Task 2"]}.
Hier sehen Sie ein Beispiel für einen cURL-Befehl, mit dem Sie die POST-Anfrage senden können:
sh
curl -X POST http://localhost:8080/api/todos \
-H "Content-Type: application/json" \
-d '{"todos": ["Task 1", "Task 2", "Task 3"]}'Die HTTP-Antwort sieht dann so aus:
sh
< HTTP/1.1 200
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 8
< Date: Mon, 27 Nov 2023 10:23:51 GMT
<
* Connection #0 to host localhost left intact
Count: 3Das Java-Spring-Boot-Projekt mit Snyk testen
In der Java-Entwicklung ist es genauso wichtig, die Sicherheit und Integrität Ihrer Anwendungen zu gewährleisten wie ihre Funktionalität. Ein wirksames Tool hierfür ist Snyk, eine Sicherheitsplattform, die sich auf das Erkennen und Beheben von Sicherheitslücken in Projektabhängigkeiten spezialisiert hat.
Java-Entwicklerinnen und -Entwickler bevorzugen oft Methoden, die sich besser in ihre bestehenden Workflows einfügen. Sehen wir uns an, wie Sie eine Java-Anwendung mit Snyk als Maven-Plugin testen können.
Snyk in Ihr Maven-Projekt integrieren
Snyk stellt ein Maven-Plugin bereit, das Sie zu Ihrer pom.xml hinzufügen können. Mit diesem Plugin können Sie Snyk-Tests als Teil Ihres Maven-Build-Prozesses ausführen.
Fügen Sie das Snyk-Maven-Plugin zu Ihrer pom.xml hinzu:
xml
<plugin>
<groupId>io.snyk</groupId>
<artifactId>snyk-maven-plugin</artifactId>
<version>2.2.0</version>
</plugin>Nachdem Sie das Plugin eingerichtet haben, müssen Sie es mit Ihrem Snyk-Konto authentifizieren. Registrieren Sie sich bei Snyk, falls Sie das noch nicht getan haben. Ein Konto können Sie kostenlos auf der Snyk-Website erstellen.
Anschließend können Sie in Ihren Snyk-Kontoeinstellungen ein Snyk-API-Token generieren und es auf Ihrem Rechner oder in Ihrer CI/CD-Umgebung als Umgebungsvariable SNYK_TOKEN festlegen. Damit das Token in der CLI für den Maven-Snyk-Test verfügbar ist, führen Sie Folgendes aus:
sh
export SNYK_TOKEN=<the Snyk API token goes here>Sie können das Snyk-Plugin auch explizit konfigurieren und apiToken sowie die Befehlszeilenargumente genauer festlegen. Diese Einstellung des Snyk-Maven-Plugins wird zur Deklaration <plugin> hinzugefügt:
xml
<configuration>
<apiToken>${env.SNYK_TOKEN}</apiToken>
<args>
<arg>--all-projects</arg>
</args>
</configuration>Anschließend können wir den Snyk-Test ausführen:
sh
mvn snyk:testOh, Snyk hat offenbar Sicherheitslücken in der neuen JSONObject-Abhängigkeit gefunden, die wir hinzugefügt haben. Sehen Sie sich das folgende Protokoll des Maven-Snyk-Tests aus dem Build-Prozess an:
sh
$ mvn snyk:test
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------------< com.example:demo >--------------------------
[INFO] Building demo 0.0.1-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- snyk:2.2.0:test (default-cli) @ demo ---
[INFO] Snyk Executable Path: /Users/lirantal/Library/Application Support/Snyk/snyk-macos
[INFO] Snyk CLI Version: 1.1254.0
[INFO]
[INFO] Testing /Users/lirantal/projects/repos/spring-boot-java-jsonobject-vulnerability...
[INFO]
[INFO] Tested 37 dependencies for known issues, found 1 issue, 1 vulnerable path.
[INFO]
[INFO]
[INFO] Issues to fix by upgrading:
[INFO]
[INFO] Upgrade org.json:json@20230618 to org.json:json@20231013 to fix
[INFO] ✗ Allocation of Resources Without Limits or Throttling [High Severity][https://security.snyk.io/vuln/SNYK-JAVA-ORGJSON-5962464] in org.json:json@20230618
[INFO] introduced by org.json:json@20230618
[INFO]
[INFO]
[INFO]
[INFO] Organization: snyk-demo-567
[INFO] Package manager: maven
[INFO] Target file: pom.xml
[INFO] Project name: com.example:demo
[INFO] Open source: no
[INFO] Project path: /Users/lirantal/projects/repos/spring-boot-java-jsonobject-vulnerability
[INFO] Licenses: enabled
[INFO]
[INFO]
[ERROR]
[ERROR] You have reached your monthly limit of 401 private tests for your snyk-demo-567 org.
[ERROR] To learn more about our plans and increase your tests limit visit https://snyk.io/plans.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 12.507 s
[INFO] Finished at: 2023-11-27T14:42:01+02:00
[INFO] ------------------------------------------------------------------------Brian Vermeer, Java Champion und Security Advocate bei Snyk, hat einen ausführlichen Blogbeitrag über die Verwendung von Snyk mit dem Maven-Plugin verfasst.
Den Out-of-Memory-Fehler in JSONObject veranschaulichen
Snyk hat eine Art Denial-of-Service-Sicherheitslücke im JSON-Parser-Paket gefunden und weitere Informationen zu diesem Sicherheitsproblem in der Snyk-Sicherheitslückendatenbank bereitgestellt.
Dort finden Sie einen Proof of Concept, den wir anwenden können, um zu verstehen, warum unser Java-API-Server anfällig ist. Wenden wir die anfällige Eingabe auf den JSON-Parser an und sehen wir uns an, was passiert.
Fügen Sie in unserem Code für TodoController.java die folgende private Methode hinzu, die eine fehlerhafte JSON-Nutzlast erzeugt:
java
private static String makeNested(int depth) {
if (depth == 0) {
return "{\"a\":1}";
}
return "{\"a\":1;\t\0" + makeNested(depth - 1) + ":1}";
}Aktualisieren Sie als Nächstes die API-Routenmethode handleTodo(), sodass dieser String als Eingabe für den Konstruktor JSONObject verwendet wird:
java
String vulnerablePayload = makeNested(30);
JSONObject jsonData = new JSONObject(vulnerablePayload);Starten Sie den Java-API-Server mit mvn spring-boot:run erneut und senden Sie die cURL-POST-HTTP-Anfrage noch einmal. Beobachten Sie, wie der Server eine Weile pausiert, bis eine Antwort zurückgegeben wird. Während dieser Pause tritt ein Speicherleck auf, und die JVM belegt immer mehr Speicher, bis die Java-Anwendung schließlich abstürzt.
Snyk hat uns bereits mitgeteilt, wie sich das Sicherheitsproblem beheben lässt. Wenn Sie den Maven-Build snyk:test erneut ausführen, sehen Sie, dass Snyk zur Behebung dieser Denial-of-Service-Sicherheitslücke ein Upgrade von Version 20230618 auf Version 20231013 empfiehlt:
sh
[INFO] Tested 37 dependencies for known issues, found 1 issue, 1 vulnerable path.
[INFO]
[INFO]
[INFO] Issues to fix by upgrading:
[INFO]
[INFO] Upgrade org.json:json@20230618 to org.json:json@20231013 to fix
[INFO] ✗ Allocation of Resources Without Limits or Throttling [High Severity][https://security.snyk.io/vuln/SNYK-JAVA-ORGJSON-5962464] in org.json:json@20230618
[INFO] introduced by org.json:json@20230618Bearbeiten Sie daher die pom.xml-Datei und aktualisieren Sie die Version der Abhängigkeit org.json auf 20231013, um das Sicherheitsproblem zu beheben.
Weitere Ressourcen zum Entwickeln, Erstellen und Bereitstellen sicherer Java-Anwendungen
Den vollständigen Quellcode zum Erstellen der Java-Spring-Boot-API mit der JSONObject-Abhängigkeit finden Sie im folgenden Repository: https://github.com/snyk-snippets/spring-boot-java-jsonobject-vulnerability
Wenn Sie hohe Ansprüche an Ihren Java-Code stellen und sich der Bereitstellung hochwertiger Produkte verschrieben haben, empfehle ich Ihnen, die folgenden Ressourcen zu den Sicherheitsaspekten von Java-Anwendungen zu lesen:
10 Best Practices für Java-Sicherheit – Spickzettel von Brian Vermeer und Jim Manico
Best Practices für die Verwaltung von Java-Abhängigkeiten – Artikel von Brian Vermeer
Ausführlicher Einblick in Serialisierung und Deserialisierung in Java: Die Java-Deserialisierungssicherheitslücke erklärt
Erste Schritte mit Snyk für die sichere Java-Entwicklung.
Das Snyk-Maven-Plugin ist Open Source und hier verfügbar: https://github.com/snyk/snyk-mvn-plugin
Besuchen Sie Snyk Learn, um mehr über die Anwendungssicherheit in Java zu erfahren
Entdecken Sie den Stand der Open-Source-Sicherheit
Erfahren Sie mehr über aktuelle Trends und Ansätze für Open-Source-Software und Supply-Chain-Sicherheit.