From 6d0237da18ed9891ae80520e400761f097b0bcdd Mon Sep 17 00:00:00 2001 From: Navaneeth Mysore Govindarajan Date: Mon, 12 Feb 2024 11:30:54 -0500 Subject: [PATCH] Simulate vuln method call when the app runs --- .java-version | 2 +- pom.xml | 1 - readme.md | 20 ++++++- .../samples/petclinic/vet/VetController.java | 56 +++++++++++++++++++ .../petclinic/MySqlIntegrationTests.java | 42 ++++++++++---- 5 files changed, 107 insertions(+), 14 deletions(-) diff --git a/.java-version b/.java-version index b4de39476..98d9bcb75 100644 --- a/.java-version +++ b/.java-version @@ -1 +1 @@ -11 +17 diff --git a/pom.xml b/pom.xml index 5b139b5ed..b4852bbd2 100644 --- a/pom.xml +++ b/pom.xml @@ -206,7 +206,6 @@ -javaagent:../runtime-agent-1.0.7.jar - -Djdk.attach.allowAttachSelf=true -Dsonatype.runtime.agent.enabled=true -Dsonatype.runtime.agent.debugMode=false -Dsonatype.runtime.agent.iq.protocol=http diff --git a/readme.md b/readme.md index 79b0fb692..6ba0b0209 100644 --- a/readme.md +++ b/readme.md @@ -6,7 +6,7 @@ [See the presentation here](https://speakerdeck.com/michaelisvy/spring-petclinic-sample-application) -## Run Petclinic locally +## Run Petclinic with the runtime agent locally Spring Petclinic is a [Spring Boot](https://spring.io/guides/gs/spring-boot) application built using [Maven](https://spring.io/guides/gs/maven/) or [Gradle](https://spring.io/guides/gs/gradle/). You can build a jar file and run it from the command line (it should work just as well with Java 17 or newer): @@ -14,7 +14,23 @@ Spring Petclinic is a [Spring Boot](https://spring.io/guides/gs/spring-boot) app git clone https://github.com/spring-projects/spring-petclinic.git cd spring-petclinic ./mvnw package -java -jar target/*.jar + +# Note: Change the path the runtime-agent-1.0.7.jar as necessary +java -javaagent:../runtime-agent-1.0.7.jar \ + -Dsonatype.runtime.agent.enabled=true \ + -Dsonatype.runtime.agent.debugMode=false \ + -Dsonatype.runtime.agent.iq.protocol=http \ + -Dsonatype.runtime.agent.iq.host=ec2-107-23-150-171.compute-1.amazonaws.com \ + -Dsonatype.runtime.agent.iq.port=8070 \ + -Dsonatype.runtime.agent.iq.user=1hPhFMQ2 \ + -Dsonatype.runtime.agent.iq.password=EBuCs4fMF3M81UNrJEZqKPK6wgn41JjC6AMvXBlzngZ5 \ + -Dsonatype.runtime.agent.iq.applicationId=spring-petclinic-runtime-agent \ + -Dsonatype.runtime.agent.isIqApplicationIdPublic=true \ + -Dsonatype.runtime.agent.blockedRunOnStartup=true \ + -Dsonatype.runtime.agent.scanClasspath=false \ + -Dsonatype.runtime.agent.fetchVulnerableClassesFromIQ=true \ + -Dsonatype.runtime.agent.vulnerableMethodDetectionEnabled=true \ + -jar target/*.jar ``` You can then access the Petclinic at . diff --git a/src/main/java/org/springframework/samples/petclinic/vet/VetController.java b/src/main/java/org/springframework/samples/petclinic/vet/VetController.java index 3240814a6..c096321fb 100644 --- a/src/main/java/org/springframework/samples/petclinic/vet/VetController.java +++ b/src/main/java/org/springframework/samples/petclinic/vet/VetController.java @@ -17,6 +17,8 @@ package org.springframework.samples.petclinic.vet; import java.util.List; +import org.springframework.core.io.buffer.DefaultDataBuffer; +import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -43,6 +45,9 @@ class VetController { @GetMapping("/vets.html") public String showVetList(@RequestParam(defaultValue = "1") int page, Model model) { + // Demo: Inject vulnerable method manually. + simulateVulnerableMethodCall(); + // Here we are returning an object of type 'Vets' rather than a collection of Vet // objects so it is simpler for Object-Xml mapping Vets vets = new Vets(); @@ -51,6 +56,57 @@ class VetController { return addPaginationModel(page, paginated, model); } + /* + * There are 4 vulnerable method signatures in this application: + * 'ch/qos/logback/classic/spi/LoggingEventVO#readObject(Ljava/io/ObjectInputStream;)V + * ', + * 'org/springframework/core/io/buffer/DefaultDataBuffer#split(I)Lorg/springframework/ + * core/io/buffer/DataBuffer; + * 'org/h2/tools/Backup#process(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String; + * Z)V + * 'ch/qos/logback/core/net/HardenedObjectInputStream#(Ljava/io/InputStream;[ + * Ljava/lang/String;)V + * + * This method simulates a vulnerable method call for demo purposes. It seems like no + * other code path call any of the vulnerable method, so manually invoking it. + * + * The following logs will be printed while navigating to + * http://localhost:8080/vets.html: Sonatype Runtime Agent - [TIME]: *** Vulnerable + * CLASS LOADED [className=org/springframework/core/io/buffer/DefaultDataBuffer] by + * the JVM Sonatype Runtime Agent - [TIME]: Assigning label 'Runtime-Class-Loaded' to + * component 22d73bef97aff8a74a99 in application: a50576c3cd894d20b24dc0d98eea084b + * Sonatype Runtime Agent - [TIME]: Component evaluation for + * [ComponentEvaluation{hash='22d73bef97aff8a74a99'}] in application + * a50576c3cd894d20b24dc0d98eea084b successful. Result + * URL=api/v2/evaluation/applications/a50576c3cd894d20b24dc0d98eea084b/results/ + * 3d62858ec88e49e0afd552066cb160ad Sonatype Runtime Agent - [TIME]: *** Class with + * vulnerable METHOD LOADED + * [className=org/springframework/core/io/buffer/DefaultDataBuffer, methodName=split, + * methodDescriptor=(I)Lorg/springframework/core/io/buffer/DataBuffer;] by the JVM + * Sonatype Runtime Agent - [TIME]: Assigning label 'Runtime-Method-Loaded' to + * component 22d73bef97aff8a74a99 in application: a50576c3cd894d20b24dc0d98eea084b + * Sonatype Runtime Agent - [TIME]: Component evaluation for + * [ComponentEvaluation{hash='22d73bef97aff8a74a99'}] in application + * a50576c3cd894d20b24dc0d98eea084b successful. Result + * URL=api/v2/evaluation/applications/a50576c3cd894d20b24dc0d98eea084b/results/ + * 47fa37da85d8447f8c101d4db35ec797 Sonatype Runtime Agent - [TIME]: *** Vulnerable + * METHOD CALLED [className=org/springframework/core/io/buffer/DefaultDataBuffer, + * methodName=split, + * methodDescriptor=(I)Lorg/springframework/core/io/buffer/DataBuffer;] Sonatype + * Runtime Agent - [TIME]: Assigning label 'Runtime-Method-Called' to component + * 22d73bef97aff8a74a99 in application: a50576c3cd894d20b24dc0d98eea084b Sonatype + * Runtime Agent - [TIME]: Component evaluation for + * [ComponentEvaluation{hash='22d73bef97aff8a74a99'}] in application + * a50576c3cd894d20b24dc0d98eea084b successful. Result + * URL=api/v2/evaluation/applications/a50576c3cd894d20b24dc0d98eea084b/results/ + * 6a969f11748f45abba95870fcd7747bb + */ + private void simulateVulnerableMethodCall() { + DefaultDataBufferFactory defaultDataBufferFactory = new DefaultDataBufferFactory(); + DefaultDataBuffer defaultDataBuffer = defaultDataBufferFactory.allocateBuffer(1024); + defaultDataBuffer.split(0); + } + private String addPaginationModel(int page, Page paginated, Model model) { List listVets = paginated.getContent(); model.addAttribute("currentPage", page); diff --git a/src/test/java/org/springframework/samples/petclinic/MySqlIntegrationTests.java b/src/test/java/org/springframework/samples/petclinic/MySqlIntegrationTests.java index f4aa85917..4046589f0 100644 --- a/src/test/java/org/springframework/samples/petclinic/MySqlIntegrationTests.java +++ b/src/test/java/org/springframework/samples/petclinic/MySqlIntegrationTests.java @@ -59,17 +59,39 @@ class MySqlIntegrationTests { @Autowired private RestTemplateBuilder builder; - void simulateVulnerableMethodCall() throws Exception { + void simulateVulnerableMethodCall() { /* - Sonatype Runtime Agent - [TIME]: *** Vulnerable CLASS LOADED [className=org/springframework/core/io/buffer/DefaultDataBuffer] by the JVM - Sonatype Runtime Agent - [TIME]: Assigning label 'Runtime-Class-Loaded' to component 22d73bef97aff8a74a99 in application: a50576c3cd894d20b24dc0d98eea084b - Sonatype Runtime Agent - [TIME]: Component evaluation for [ComponentEvaluation{hash='22d73bef97aff8a74a99'}] in application a50576c3cd894d20b24dc0d98eea084b successful. Result URL=api/v2/evaluation/applications/a50576c3cd894d20b24dc0d98eea084b/results/3d62858ec88e49e0afd552066cb160ad - Sonatype Runtime Agent - [TIME]: *** Class with vulnerable METHOD LOADED [className=org/springframework/core/io/buffer/DefaultDataBuffer, methodName=split, methodDescriptor=(I)Lorg/springframework/core/io/buffer/DataBuffer;] by the JVM - Sonatype Runtime Agent - [TIME]: Assigning label 'Runtime-Method-Loaded' to component 22d73bef97aff8a74a99 in application: a50576c3cd894d20b24dc0d98eea084b - Sonatype Runtime Agent - [TIME]: Component evaluation for [ComponentEvaluation{hash='22d73bef97aff8a74a99'}] in application a50576c3cd894d20b24dc0d98eea084b successful. Result URL=api/v2/evaluation/applications/a50576c3cd894d20b24dc0d98eea084b/results/47fa37da85d8447f8c101d4db35ec797 - Sonatype Runtime Agent - [TIME]: *** Vulnerable METHOD CALLED [className=org/springframework/core/io/buffer/DefaultDataBuffer, methodName=split, methodDescriptor=(I)Lorg/springframework/core/io/buffer/DataBuffer;] - Sonatype Runtime Agent - [TIME]: Assigning label 'Runtime-Method-Called' to component 22d73bef97aff8a74a99 in application: a50576c3cd894d20b24dc0d98eea084b - Sonatype Runtime Agent - [TIME]: Component evaluation for [ComponentEvaluation{hash='22d73bef97aff8a74a99'}] in application a50576c3cd894d20b24dc0d98eea084b successful. Result URL=api/v2/evaluation/applications/a50576c3cd894d20b24dc0d98eea084b/results/6a969f11748f45abba95870fcd7747bb + * Sonatype Runtime Agent - [TIME]: *** Vulnerable CLASS LOADED + * [className=org/springframework/core/io/buffer/DefaultDataBuffer] by the JVM + * Sonatype Runtime Agent - [TIME]: Assigning label 'Runtime-Class-Loaded' to + * component 22d73bef97aff8a74a99 in application: a50576c3cd894d20b24dc0d98eea084b + * Sonatype Runtime Agent - [TIME]: Component evaluation for + * [ComponentEvaluation{hash='22d73bef97aff8a74a99'}] in application + * a50576c3cd894d20b24dc0d98eea084b successful. Result + * URL=api/v2/evaluation/applications/a50576c3cd894d20b24dc0d98eea084b/results/ + * 3d62858ec88e49e0afd552066cb160ad Sonatype Runtime Agent - [TIME]: *** Class + * with vulnerable METHOD LOADED + * [className=org/springframework/core/io/buffer/DefaultDataBuffer, + * methodName=split, + * methodDescriptor=(I)Lorg/springframework/core/io/buffer/DataBuffer;] by the JVM + * Sonatype Runtime Agent - [TIME]: Assigning label 'Runtime-Method-Loaded' to + * component 22d73bef97aff8a74a99 in application: a50576c3cd894d20b24dc0d98eea084b + * Sonatype Runtime Agent - [TIME]: Component evaluation for + * [ComponentEvaluation{hash='22d73bef97aff8a74a99'}] in application + * a50576c3cd894d20b24dc0d98eea084b successful. Result + * URL=api/v2/evaluation/applications/a50576c3cd894d20b24dc0d98eea084b/results/ + * 47fa37da85d8447f8c101d4db35ec797 Sonatype Runtime Agent - [TIME]: *** + * Vulnerable METHOD CALLED + * [className=org/springframework/core/io/buffer/DefaultDataBuffer, + * methodName=split, + * methodDescriptor=(I)Lorg/springframework/core/io/buffer/DataBuffer;] Sonatype + * Runtime Agent - [TIME]: Assigning label 'Runtime-Method-Called' to component + * 22d73bef97aff8a74a99 in application: a50576c3cd894d20b24dc0d98eea084b Sonatype + * Runtime Agent - [TIME]: Component evaluation for + * [ComponentEvaluation{hash='22d73bef97aff8a74a99'}] in application + * a50576c3cd894d20b24dc0d98eea084b successful. Result + * URL=api/v2/evaluation/applications/a50576c3cd894d20b24dc0d98eea084b/results/ + * 6a969f11748f45abba95870fcd7747bb */ DefaultDataBufferFactory defaultDataBufferFactory = new DefaultDataBufferFactory(); DefaultDataBuffer defaultDataBuffer = defaultDataBufferFactory.allocateBuffer(1024);