GHSA-4f5f-j737-pm58: Input Validation
Summary The rexlist component reads the SQL sort column directly from the sort GET parameter without validating it against the set of columns declared sortable via setColumnSortable(). Although the value is wrapped in backticks via escapeIdentifier() (preventing classical SQL injection), this still allows any authenticated backend user to ORDER BY any column in the query's FROM tables, including unselected sensitive columns such as password from the rexuser table, and perform error-based column enumeration.
Details File: redaxo/src/core/lib/list.php:976-982 — getSortColumn() returns the raw request parameter without whitelist check: php public function getSortColumn($default = null) { if (rexrequest('list', 'string') == $this->getName()) { return rexrequest('sort', 'string', $default); // NO validation against sortable columns } return $default; }
File: redaxo/src/core/lib/list.php:899-911 — prepareQuery() uses it directly in the ORDER BY clause: php protected function prepareQuery($query, array $defaultSort = []) { $sortColumn = $this->getSortColumn(); if ('' != $sortColumn) { $sql = rexsql::factory($this->db); $sortColumn = $sql->escapeIdentifier($sortColumn); // backtick-wraps, but no whitelist if ($defaultSort || false === stripos($query, ' ORDER BY ')) { $query .= ' ORDER BY ' . $sortColumn . ' ' . $sortType; } }
The users list queries rexuser which contains password, previouspasswords, passwordchangerequired — not in the SELECT. Specifying a non-existent column name produces a MySQL Unknown column exception whose message is propagated to the user, confirming or denying column existence.
PoC Column enumeration (error-based): GET /redaxo/index.php?page=users&list=<listname>&sort=nonexistentcol&sorttype=asc Response will contain: Unknown column 'nonexistentcol' in 'order clause'
Sort by password hash (data ordering leak): GET /redaxo/index.php?page=users&list=<listname>&sort=password&sorttype=asc Users are silently reordered by their Argon2 password hash.
Impact Authenticated backend users (non-admin) can enumerate database column names of internal tables via error messages and manipulate query ordering to include sensitive unselected columns. While this does not allow arbitrary SQL execution due to backtick escaping, it constitutes an information disclosure vulnerability enabling targeted further attacks.
Fix Validate the sort request parameter against the whitelist of columns registered with setColumnSortable() before use in the query: php public function getSortColumn($default = null) { if (rexrequest('list', 'string') == $this->getName()) { $requested = rexrequest('sort', 'string', $default); if ($requested !== null && $this->hasColumnOption($requested, REXLISTOPTSORT)) { return $requested; } } return $default; }
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
composer/redaxo/sourceto a version that resolves this vulnerability.Fixed in 5.21.2 - Configuration
Validate the sort request parameter against the columns registered with setColumnSortable() before using it in the ORDER BY clause.
rex_list sort request parameter validation = whitelist of columns registered with setColumnSortable()
Event History
Frequently Asked Questions
Who can exploit this issue?
Any authenticated backend user who can send requests to an affected rex_list component can supply a sort parameter. The issue is remotely reachable and does not require user interaction, but it requires low-level privileges.
What can an attacker do with the sort parameter?
They can order query results by arbitrary columns available in the query's FROM tables, including sensitive columns that were not selected for display, such as a password column in the rex_user table. They can also use database errors to enumerate available columns; the identifier escaping prevents classical SQL injection.
Are only columns configured as sortable affected?
No. The vulnerable getSortColumn() behavior does not validate the requested sort value against the columns declared sortable with setColumnSortable().
How can I identify attempted exploitation?
Review backend requests for rex_list operations where the sort GET parameter contains column names not configured as sortable for the relevant list. Database or application errors caused by invalid ORDER BY column names may also indicate column-enumeration attempts.