Skip to content

Arbitrary directory deletion via stored cluster name (path traversal) #1204

Description

@Ku4D3

Severity: High · CWE: CWE-22 (Improper Limitation of a Pathname to a Restricted Directory)
Affected versions:v1.4.0

Summary

Creating a cluster accepts a free-text cluster name and persists it after only a uniqueness check, with no validation of path characters. The stored name is later used verbatim to build a kerberos work directory under the temp root; when a component's kerberos configuration is refreshed, that directory is recursively deleted via FileUtils.deleteDirectory. A clusterName containing ../ (or resolving above the temp root) causes the recursive delete to target an unintended directory, letting an authenticated operator delete arbitrary directories.

Vulnerability chain

Stage Component Location
Source clusterName parameter (POST /cluster/addCluster) ClusterController.java:56
Storage cluster.setClusterName(clusterName) persisted, no path validation ConsoleClusterService.java:72
Read getLocalKerberosPathtempDir + sep + clusterName + ... ConsoleComponentService.java:617
Sink FileUtils.deleteDirectory(new File(kerberosPath)) ConsoleComponentService.java:494

addCluster persists the caller-supplied clusterName after only checking that the name is unique. Later, when a component's kerberos files are uploaded or refreshed, updateComponentKerberosFile computes the local kerberos path through getLocalKerberosPath, which concatenates the temp directory, the stored cluster name, the component type, and kerberos. That path is passed to FileUtils.deleteDirectory to clear the old kerberos directory before extraction. Because the cluster name is an unvalidated path component, a ../-bearing or absolute-looking name resolves the delete target outside the temp root.

Key code

Stored unvalidated — taier-data-develop/.../controller/console/ClusterController.java:55:

@PostMapping(value = "/addCluster")
public R<Long> addCluster(@RequestParam("clusterName") String clusterName) {
    return R.ok(consoleClusterService.addCluster(clusterName));
}

taier-data-develop/.../service/console/ConsoleClusterService.java:67:

public Long addCluster(String clusterName) {
    if (clusterMapper.getByClusterName(clusterName) != null) { ... }
    Cluster cluster = new Cluster();
    cluster.setClusterName(clusterName);   // no path-character validation
    clusterMapper.insert(cluster);
    return cluster.getId();
}

Path built from the stored name — ConsoleComponentService.java:612:

public String getLocalKerberosPath(Long clusterId, Integer componentCode) {
    Cluster one = clusterMapper.getOne(clusterId);
    ...
    return env.getTempDir() + File.separator + one.getClusterName()
           + File.separator + EComponentType.getByCode(componentCode).name() + File.separator + KERBEROS;
}

Recursive delete on the resolved path — ConsoleComponentService.java:492:

String kerberosPath = this.getLocalKerberosPath(clusterId, addComponent.getComponentTypeCode());
try {
    FileUtils.deleteDirectory(new File(kerberosPath));   // :494
} catch (IOException e) { ... }

Proof of Concept

Authenticated console operator. The requests only set up and trigger the delete; the target is a benign /tmp path and no destructive payload is delivered.

Step 1 — create a cluster whose name resolves above the temp root:

POST /cluster/addCluster HTTP/1.1
Host: <taier host>
Content-Type: application/x-www-form-urlencoded
Cookie: <taier session>

clusterName=../../../../../../../../tmp/x

Step 2 — refresh a component's kerberos configuration for that cluster (e.g. via /upload/component/addOrUpdateComponent or /upload/component/uploadKerberos), which calls updateComponentKerberosFilegetLocalKerberosPathFileUtils.deleteDirectory(...) on the path derived from the stored name.

Impact

An authenticated operator with cluster/component-management access can cause taier to recursively delete directories outside its temp root. This can lead to denial of service or destruction of data reachable (and deletable) by the JVM user. Precondition: a valid authenticated session.

Remediation

Validate clusterName to identifier-safe characters and reject /, \, and .. before persisting. Derive filesystem paths from a non-user-controlled identifier (e.g. the numeric clusterId) rather than the free-text cluster name. Before deleting, canonicalize the resolved path and confirm it remains inside the temp root.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions