From 60a560f51e3ad5b46509e796007ff5e04c15cc8f Mon Sep 17 00:00:00 2001 From: Morten Svanaes Date: Tue, 5 May 2026 04:01:23 +0800 Subject: [PATCH] fix: quote SQL view filter column name to block identifier-slot injection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The filter column name was concatenated raw into the generated WHERE clause in DefaultSqlViewService.getFilterQuery, mirroring the same shape that getCriteriaSqlClause already handles correctly via statementBuilder.columnQuote(). Two independent reports demonstrate the missed sink is exploitable for arbitrary SQL execution by any authenticated user with read access to a SQL View: - GHSA-pwmg-mvjw-4m23 — error-based exfil via CAST((subquery) AS int) - internal report — UNION SELECT smuggled through the column-name slot Wrapping the column name with statementBuilder.columnQuote() turns the whole user-supplied string into a single Postgres identifier, which Postgres rejects at parse time when it doesn't exist — preventing the inner SQL from being evaluated. This is exactly the defense already in place for the parallel sink in getCriteriaSqlClause. Note: the master/2.40-2.42 backports use SqlUtils.quote() and ship companion regression tests in SqlViewControllerIntegrationTest. On 2.39 the matching defense API is statementBuilder.columnQuote() and the regression test class does not exist, so only the fix is applied. AI Assisted Refs GHSA-pwmg-mvjw-4m23, DHIS2-21425 --- .../main/java/org/hisp/dhis/sqlview/DefaultSqlViewService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/sqlview/DefaultSqlViewService.java b/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/sqlview/DefaultSqlViewService.java index 266e4edfae67..c8a14cdeb386 100644 --- a/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/sqlview/DefaultSqlViewService.java +++ b/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/sqlview/DefaultSqlViewService.java @@ -208,7 +208,7 @@ private String getFilterQuery( query += sqlHelper.whereAnd() + " " - + columnName + + statementBuilder.columnQuote(columnName) + " " + QueryUtils.parseFilterOperator(operator, value);