| tiêu đề | DTStack taier v1.4.0 Path Traversal |
|---|
| Mô tả | Summary
Several component-upload endpoints under /upload/component/* save an uploaded multipart file to a path built directly from the caller-supplied filename with no sanitization. Because the destination is computed as uploadsDir + separator + originalFilename, a filename containing ../ escapes the intended upload directory, letting an authenticated operator write or overwrite arbitrary files writable by the JVM user.
Vulnerability chain
Stage Component Location
Source Multipart filename of uploaded component resources UploadController.java:146
Sink transferTo(uploadsDir + sep + originalFilename) (no sanitize) UploadController.java:147,153
A shared helper, getResourcesFromFiles, is invoked by the component-upload endpoints (/upload/component/config, /upload/component/addOrUpdateComponent, /upload/component/parseKerberos, /upload/component/uploadKerberos). It reads MultipartFile.getOriginalFilename() verbatim, concatenates it onto the upload base directory, creates any missing parent directories, and writes the bytes with transferTo. No /, \, or .. sequence is rejected, and no canonical containment check is performed, so a traversal payload in the multipart filename resolves outside the base directory.
Key code
taier-data-develop/.../controller/console/UploadController.java:143
for (MultipartFile file : files) {
String fileOriginalName = file.getOriginalFilename();
String path = uploadsDir + File.separator + fileOriginalName; // :147 — no sanitize
File saveFile = new File(path);
if (!saveFile.getParentFile().exists()) {
saveFile.getParentFile().mkdirs(); // :150 — also creates escaped parent dirs
}
try {
file.transferTo(saveFile); // :153
} catch (Exception e) { ... }
The upload base directory is the working directory plus file-uploads — UploadController.java:58:
private static String uploadsDir = System.getProperty("user.dir") + File.separator + "file-uploads";
Proof of Concept
Authenticated console operator. The request only triggers the write; the target is a benign /tmp path.
POST /upload/component/config HTTP/1.1
Host: <taier host>
Content-Type: multipart/form-data; boundary=----b
Cookie: <taier session>
------b
Content-Disposition: form-data; name="fileName"; filename="../../../../../../tmp/x.txt"
Content-Type: application/octet-stream
x
------b
Content-Disposition: form-data; name="componentType"
0
------b--
The same sink applies to /upload/component/parseKerberos, /upload/component/addOrUpdateComponent, and /upload/component/uploadKerberos, which all pass uploaded files through getResourcesFromFiles.
Impact
An authenticated operator with component-management access can write or overwrite any file reachable and writable by the taier JVM user. Depending on the deployment, this can lead to remote code execution (e.g., dropping classes, scripts, or JARs onto a writable classpath or writable configuration consumed by the application). Precondition: a valid authenticated session.
Remediation
Do not trust MultipartFile.getOriginalFilename() as a filesystem component. Generate a safe server-side name (e.g., a UUID or content hash) for storage and keep the original name only as metadata; reject any /, \, or .. sequence in the original filename. Additionally, canonicalize the resolved destination and verify it remains inside the upload base directory before writing. |
|---|
| Nguồn | ⚠️ https://github.com/DTStack/Taier/issues/1202 |
|---|
| Người dùng | Ku4D3 (UID 97639) |
|---|
| Đệ trình | 25/06/2026 10:30 (cách đây 2 các tháng) |
|---|
| Kiểm duyệt | 13/08/2026 18:44 (2 months later) |
|---|
| Trạng thái | được chấp nhận |
|---|
| Mục VulDB | 389664 [DTStack Taier 1.4.0 Upload Controller UploadController.java MultipartFile.getOriginalFilename Tệp tin duyệt thư mục] |
|---|
| điểm | 20 |
|---|