diff --git a/google/README.md b/google/README.md index f9493cf98..a8b7d4bea 100644 --- a/google/README.md +++ b/google/README.md @@ -44,6 +44,9 @@ This directory contains all Tsunami plugins published by Google. * [Tomcat Ghostcat (CVE-2020-1938) Detector](https://github.com/google/tsunami-security-scanner-plugins/tree/master/google/detectors/rce/tomcat/ghostcat) * [vBulletin Pre-Auth RCE (CVE-2019-16759) Detector](https://github.com/google/tsunami-security-scanner-plugins/tree/master/google/detectors/rce/vbulletin/cve201916759) +#### Directory Traversal +* [Node-RED-Dashboard directory traversal vulnerability (CVE-2021-3223) Detector](https://github.com/google/tsunami-security-scanner-plugins/tree/master/templated/templateddetector/plugins/cve/2021/NodeRed_CVE_2021_3223.textproto) + ## Planned Detectors * Exposed unauthenticated [Adminer](https://www.adminer.org/) server. diff --git a/google/detectors/directorytraversal/cve20213223/README.md b/google/detectors/directorytraversal/cve20213223/README.md deleted file mode 100644 index a11c46be9..000000000 --- a/google/detectors/directorytraversal/cve20213223/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Node-RED-Dashboard Directory Traversal Detector (CVE 2021-3223) - -This Tsunami plugin tests to see if the traversal of `ui_base/js/..%2f` directory is vulnerable to remote attackers, allowing them to read arbitrary files. - -## Build jar file for this plugin - -Using `gradlew`: - -```shell -./gradlew jar -``` - -Tsunami identifiable jar file is located at `build/libs` directory. diff --git a/google/detectors/directorytraversal/cve20213223/build.gradle b/google/detectors/directorytraversal/cve20213223/build.gradle deleted file mode 100644 index 8de3129b9..000000000 --- a/google/detectors/directorytraversal/cve20213223/build.gradle +++ /dev/null @@ -1,39 +0,0 @@ -plugins { - id 'java-library' -} - -description = 'Tsunami NodeRedDashboard DirectoryTraversal 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 "org.mockito:mockito-core:5.18.0" - testImplementation "com.squareup.okhttp3:mockwebserver:3.12.0" - testImplementation "com.google.truth:truth:1.4.4" - 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/google/detectors/directorytraversal/cve20213223/settings.gradle b/google/detectors/directorytraversal/cve20213223/settings.gradle deleted file mode 100644 index d53002c2c..000000000 --- a/google/detectors/directorytraversal/cve20213223/settings.gradle +++ /dev/null @@ -1,12 +0,0 @@ -rootProject.name = 'nodereddashboard_directorytraversal' - -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/google/detectors/directorytraversal/cve20213223/src/main/java/com/google/tsunami/plugins/detectors/directorytraversal/cve20213223/NodeRedDashboardDirectoryTraversalDetector.java b/google/detectors/directorytraversal/cve20213223/src/main/java/com/google/tsunami/plugins/detectors/directorytraversal/cve20213223/NodeRedDashboardDirectoryTraversalDetector.java deleted file mode 100644 index 6f002fb2e..000000000 --- a/google/detectors/directorytraversal/cve20213223/src/main/java/com/google/tsunami/plugins/detectors/directorytraversal/cve20213223/NodeRedDashboardDirectoryTraversalDetector.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2022 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.directorytraversal.cve20213223; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.collect.ImmutableList.toImmutableList; -import static com.google.tsunami.common.net.http.HttpRequest.get; - -import com.google.common.collect.ImmutableList; -import com.google.common.flogger.GoogleLogger; -import com.google.gson.JsonSyntaxException; -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.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.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.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.Instant; -import javax.inject.Inject; - -/** NodeRedDashboardDirectoryTraversalDetector plugin. */ -// PluginInfo tells Tsunami scanning engine basic information about the plugin. -@PluginInfo( - type = PluginType.VULN_DETECTION, - name = "NodeRedDashboardDirectoryTraversalDetector", - version = "0.1", - description = "This plugin detects directory traversal vulnerability in Node-RED-Dashboard.", - author = "Tsunami Team (tsunami-dev@google.com)", - bootstrapModule = NodeRedDashboardDirectoryTraversalDetectorBootstrapModule.class) -public final class NodeRedDashboardDirectoryTraversalDetector implements VulnDetector { - private static final GoogleLogger logger = GoogleLogger.forEnclosingClass(); - - private final Clock utcClock; - private final HttpClient httpClient; - - // All the utility dependencies of the plugin must be injected through the constructor of the - // detector. Here the UtcClock is provided by the scanner. - @Inject - NodeRedDashboardDirectoryTraversalDetector(@UtcClock Clock utcClock, HttpClient httpClient) { - this.utcClock = checkNotNull(utcClock); - this.httpClient = checkNotNull(httpClient).modify().setFollowRedirects(false).build(); - } - - @Override - public ImmutableList getAdvisories() { - return ImmutableList.of(getAdvisory(AdditionalDetail.getDefaultInstance())); - } - - // Main entry point of VulnDetector. Both parameters will be populated by the scanner. - // targetInfo contains the general information about the scan target. - // matchedServices parameter contains all exposed network services on the scan target. - @Override - public DetectionReportList detect( - TargetInfo targetInfo, ImmutableList matchedServices) { - logger.atInfo().log("NodeRedDashboardDirectoryTraversalDetector starts detecting."); - - return DetectionReportList.newBuilder() - .addAllDetectionReports( - matchedServices.stream() - .filter(NetworkServiceUtils::isWebService) - // Check individual NetworkService whether it is vulnerable. - .filter(this::isServiceVulnerable) - // Build DetectionReport message for vulnerable services. - .map(networkService -> buildDetectionReport(targetInfo, networkService)) - .collect(toImmutableList())) - .build(); - } - - Vulnerability getAdvisory(AdditionalDetail details) { - return Vulnerability.newBuilder() - .setMainId(VulnerabilityId.newBuilder().setPublisher("GOOGLE").setValue("CVE_2021_3223")) - .setSeverity(Severity.CRITICAL) - .setTitle("Node-RED-Dashboard directory traversal vulnerability") - .addRelatedId(VulnerabilityId.newBuilder().setPublisher("CVE").setValue("CVE-2021-3223")) - .setDescription("Directory Traversal vulnerability in exposed Node-RED-Dashboard") - .setRecommendation("Upgrade node-red-dashboard to version 2.26.2 or greater.") - .addAdditionalDetails(details) - .build(); - } - - // Checks whether a given network service is vulnerable. - private boolean isServiceVulnerable(NetworkService networkService) { - String targetUri = - NetworkServiceUtils.buildWebApplicationRootUrl(networkService) + "ui_base/js/..%2f"; - try { - logger.atInfo().log("Node-RED starts checking for target URI: '%s'.", targetUri); - - HttpResponse response = - httpClient.send(get(targetUri).withEmptyHeaders().build(), networkService); - - // If accessing targetUri does not give not found error, then returns true - return response.status().isSuccess() - && response.bodyString().get().contains("Welcome to the Node-RED Dashboard"); - } catch (IOException e) { - logger.atWarning().withCause(e).log("Unable to query '%s'.", targetUri); - return false; - } catch (JsonSyntaxException e) { - logger.atWarning().withCause(e).log( - "JSON syntax error occurred parsing response for target URI: '%s'.", targetUri); - return false; - } - } - - // This builds the DetectionReport message for a specific vulnerable network service. - private DetectionReport buildDetectionReport( - TargetInfo targetInfo, NetworkService vulnerableNetworkService) { - TextData details = - TextData.newBuilder() - .setText( - String.format( - "Node-RED-Dashboard before 2.26.2 allows %s directory traversal to read files.", - NetworkServiceUtils.buildWebApplicationRootUrl(vulnerableNetworkService) - + "ui_base/js/..%2f")) - .build(); - return DetectionReport.newBuilder() - .setTargetInfo(targetInfo) - .setNetworkService(vulnerableNetworkService) - .setDetectionTimestamp(Timestamps.fromMillis(Instant.now(utcClock).toEpochMilli())) - .setDetectionStatus(DetectionStatus.VULNERABILITY_VERIFIED) - .setVulnerability(getAdvisory(AdditionalDetail.newBuilder().setTextData(details).build())) - .build(); - } -} diff --git a/google/detectors/directorytraversal/cve20213223/src/main/java/com/google/tsunami/plugins/detectors/directorytraversal/cve20213223/NodeRedDashboardDirectoryTraversalDetectorBootstrapModule.java b/google/detectors/directorytraversal/cve20213223/src/main/java/com/google/tsunami/plugins/detectors/directorytraversal/cve20213223/NodeRedDashboardDirectoryTraversalDetectorBootstrapModule.java deleted file mode 100644 index 162826c3b..000000000 --- a/google/detectors/directorytraversal/cve20213223/src/main/java/com/google/tsunami/plugins/detectors/directorytraversal/cve20213223/NodeRedDashboardDirectoryTraversalDetectorBootstrapModule.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2022 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.directorytraversal.cve20213223; - -import com.google.tsunami.plugin.PluginBootstrapModule; - -/** An example Guice module that bootstraps the {@link NodeRedDashboardExposedDirDetector}. */ -public final class NodeRedDashboardDirectoryTraversalDetectorBootstrapModule - extends PluginBootstrapModule { - - @Override - protected void configurePlugin() { - - // registerPlugin method is required in order for the Tsunami scanner to identify the new plugin - registerPlugin(NodeRedDashboardDirectoryTraversalDetector.class); - } -} diff --git a/google/detectors/directorytraversal/cve20213223/src/test/java/com/google/tsunami/plugins/detectors/directorytraversal/cve20213223/NodeRedDashboardDirectoryTraversalDetectorTest.java b/google/detectors/directorytraversal/cve20213223/src/test/java/com/google/tsunami/plugins/detectors/directorytraversal/cve20213223/NodeRedDashboardDirectoryTraversalDetectorTest.java deleted file mode 100644 index e710edfaa..000000000 --- a/google/detectors/directorytraversal/cve20213223/src/test/java/com/google/tsunami/plugins/detectors/directorytraversal/cve20213223/NodeRedDashboardDirectoryTraversalDetectorTest.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2022 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.directorytraversal.cve20213223; - -import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat; -import static com.google.tsunami.common.data.NetworkEndpointUtils.forHostname; -import static com.google.tsunami.common.data.NetworkEndpointUtils.forHostnameAndPort; - -import com.google.common.collect.ImmutableList; -import com.google.inject.Guice; -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.proto.AdditionalDetail; -import com.google.tsunami.proto.DetectionReport; -import com.google.tsunami.proto.DetectionStatus; -import com.google.tsunami.proto.NetworkEndpoint; -import com.google.tsunami.proto.NetworkService; -import com.google.tsunami.proto.Software; -import com.google.tsunami.proto.TargetInfo; -import com.google.tsunami.proto.TextData; -import com.google.tsunami.proto.TransportProtocol; -import java.io.IOException; -import java.time.Instant; -import javax.inject.Inject; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -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 NodeRedDashboardDirectoryTraversalDetector}. */ -@RunWith(JUnit4.class) -public final class NodeRedDashboardDirectoryTraversalDetectorTest { - - private final FakeUtcClock fakeUtcClock = - FakeUtcClock.create().setNow(Instant.parse("2022-01-01T00:00:00.00Z")); - - private MockWebServer mockWebServer; - - @Inject private NodeRedDashboardDirectoryTraversalDetector detector; - - @Before - public void setUp() { - mockWebServer = new MockWebServer(); - - Guice.createInjector( - new FakeUtcClockModule(fakeUtcClock), - new HttpClientModule.Builder().build(), - new NodeRedDashboardDirectoryTraversalDetectorBootstrapModule()) - .injectMembers(this); - } - - @After - public void tearDown() throws IOException { - mockWebServer.shutdown(); - } - - // In Tsunami, unit test names follow the following general convention: - // functionUnderTest_condition_outcome. - - // Test for the case when the node-red directory is exposed - @Test - public void detect_whenNodeRedDashboardDirExposed_reportsVuln() throws IOException { - startMockWebServer( - "/ui_base/js/..%2f", HttpStatus.OK.code(), "Welcome to the Node-RED Dashboard"); - ImmutableList httpServices = - ImmutableList.of( - NetworkService.newBuilder() - .setNetworkEndpoint( - forHostnameAndPort(mockWebServer.getHostName(), mockWebServer.getPort())) - .setTransportProtocol(TransportProtocol.TCP) - .setSoftware(Software.newBuilder().setName("Node-RED-Dashboard directory")) - .setServiceName("http") - .build()); - - assertThat( - detector - .detect(buildTargetInfo(forHostname(mockWebServer.getHostName())), httpServices) - .getDetectionReportsList()) - .containsExactly( - DetectionReport.newBuilder() - .setTargetInfo(buildTargetInfo(forHostname(mockWebServer.getHostName()))) - .setNetworkService(httpServices.get(0)) - .setDetectionTimestamp(Timestamps.fromMillis(fakeUtcClock.millis())) - .setDetectionStatus(DetectionStatus.VULNERABILITY_VERIFIED) - .setVulnerability( - detector.getAdvisory( - AdditionalDetail.newBuilder() - .setTextData( - TextData.newBuilder() - .setText( - String.format( - "Node-RED-Dashboard before 2.26.2 allows" - + " http://%s:%d/ui_base/js/..%%2f directory" - + " traversal to read files.", - mockWebServer.getHostName(), mockWebServer.getPort()))) - .build())) - .build()); - } - - // Test for the case when the node-red directory is not exposed, hence safe - @Test - public void detect_whenNodeRedDashboardDirNotFound_doesNotReportVuln() throws IOException { - startMockWebServer("/ui_base/js/..%2f", HttpStatus.NOT_FOUND.code(), ""); - ImmutableList httpServices = - ImmutableList.of( - NetworkService.newBuilder() - .setNetworkEndpoint( - forHostnameAndPort(mockWebServer.getHostName(), mockWebServer.getPort())) - .setTransportProtocol(TransportProtocol.TCP) - .setSoftware(Software.newBuilder().setName("Node-RED-Dashboard directory")) - .setServiceName("http") - .build()); - - assertThat( - detector - .detect(buildTargetInfo(forHostname(mockWebServer.getHostName())), httpServices) - .getDetectionReportsList()) - .isEmpty(); - } - - // Test for the case when it is not a node-red directory - @Test - public void detect_whenNonNodeRedDashboardDir_ignoresServices() throws IOException { - startMockWebServer("/ui_base/js/..%2f", HttpStatus.OK.code(), "This is WordPress."); - ImmutableList httpServices = - ImmutableList.of( - NetworkService.newBuilder() - .setNetworkEndpoint( - forHostnameAndPort(mockWebServer.getHostName(), mockWebServer.getPort())) - .setTransportProtocol(TransportProtocol.TCP) - .setSoftware(Software.newBuilder().setName("WordPress")) - .setServiceName("http") - .build()); - - assertThat( - detector - .detect(buildTargetInfo(forHostname(mockWebServer.getHostName())), httpServices) - .getDetectionReportsList()) - .isEmpty(); - } - - // Test for the case when it is not an Http network service - @Test - public void detect_whenNonHttpNetworkService_ignoresServices() { - ImmutableList nonHttpServices = - ImmutableList.of( - NetworkService.newBuilder().setServiceName("ssh").build(), - NetworkService.newBuilder().setServiceName("rdp").build()); - assertThat( - detector - .detect(buildTargetInfo(forHostname(mockWebServer.getHostName())), nonHttpServices) - .getDetectionReportsList()) - .isEmpty(); - } - - // Test for the case when the network service is empty - @Test - public void detect_whenEmptyNetworkService_generatesEmptyDetectionReports() { - assertThat( - detector - .detect( - buildTargetInfo(forHostname(mockWebServer.getHostName())), ImmutableList.of()) - .getDetectionReportsList()) - .isEmpty(); - } - - private void startMockWebServer(String url, int responseCode, String response) - throws IOException { - mockWebServer.enqueue(new MockResponse().setResponseCode(responseCode).setBody(response)); - mockWebServer.start(); - mockWebServer.url(url); - } - - private static TargetInfo buildTargetInfo(NetworkEndpoint networkEndpoint) { - return TargetInfo.newBuilder().addNetworkEndpoints(networkEndpoint).build(); - } -} diff --git a/templated/templateddetector/plugins/cve/2021/NodeRed_CVE_2021_3223.textproto b/templated/templateddetector/plugins/cve/2021/NodeRed_CVE_2021_3223.textproto new file mode 100644 index 000000000..95dd0d35a --- /dev/null +++ b/templated/templateddetector/plugins/cve/2021/NodeRed_CVE_2021_3223.textproto @@ -0,0 +1,82 @@ +# proto-file: proto/templated_plugin.proto +# proto-message: TemplatedPlugin + +############### +# PLUGIN INFO # +############### + +info: { + type: VULN_DETECTION + name: "NodeRed_CVE_2021_3223" + author: + "Robert Dick (robert@doyensec.com) for the Templated version, " + "Tsunami Team (tsunami-dev@google.com) for the original Java version" + version: "2.0" +} + +finding: { + main_id: { + publisher: "GOOGLE" + value: "CVE_2021_3223" + } + title: "Node-RED-Dashboard directory traversal vulnerability (CVE-2021-3223)" + description: "Directory Traversal vulnerability in exposed Node-RED-Dashboard" + recommendation: "Upgrade node-red-dashboard to version 2.26.2 or greater." + severity: CRITICAL + related_id: { + publisher: "CVE" + value: "CVE-2021-3223" + } +} + +########### +# ACTIONS # +########### + +# one step to check for /etc/passwd, changed from original detector +# because the original detector did not work correctly. + +actions: { + name: "fingerprint_nodered" + http_request: { + method: GET + uri: "/" + response: { + http_status: 200 + expect_any: { + conditions: [ + { body: {} contains: "Node-RED" } + ] + } + } + } +} + + +actions: { + name: "check_traversal" + http_request: { + method: GET + uri: "/ui_base/js/..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc/passwd" + response: { + http_status: 200 + expect_any: { + conditions: [ + { body: {} contains: "root:x:0:0" }, + { body: {} contains: "root:*:0:0" } + ] + } + } + } +} + +############# +# WORKFLOWS # +############# + +workflows: { + actions: [ + "fingerprint_nodered", + "check_traversal" + ] +} \ No newline at end of file diff --git a/templated/templateddetector/plugins/cve/2021/NodeRed_CVE_2021_3223_test.textproto b/templated/templateddetector/plugins/cve/2021/NodeRed_CVE_2021_3223_test.textproto new file mode 100644 index 000000000..4def450fc --- /dev/null +++ b/templated/templateddetector/plugins/cve/2021/NodeRed_CVE_2021_3223_test.textproto @@ -0,0 +1,75 @@ +# proto-file: proto/templated_plugin_tests.proto +# proto-message: TemplatedPluginTests + +config: { + tested_plugin: "NodeRed_CVE_2021_3223" +} + +tests: { + name: "whenVuln_returnsVuln" + expect_vulnerability: true + + mock_http_server: { + mock_responses: [ + { + uri: "/" + status: 200 + body_content: + "... Node-RED ..." + }, + { + uri: "/ui_base/js/..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc/passwd" + status: 200 + body_content: + "root:x:0:0:root:/root:/bin/ash\n" + "bin:x:1:1:bin:/bin:/sbin/nologin" + }, + { + uri: "TSUNAMI_MAGIC_ANY_URI" + status: 200 + body_content: '{"status":200}' + } + ] + } +} + +tests: { + name: "whenNotVuln_returnsNotVuln" + expect_vulnerability: false + + mock_http_server: { + mock_responses: [ + { + uri: "/" + status: 200 + body_content: '... Node-RED ...' + }, + { + uri: "/ui_base/js/..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc/passwd" + status: 404 + body_content: 'Not Found' + }, + { + 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 ..." + } + ] + } +}