ILIAS: SQL injection in the MyStaff lists

A low-privileged Kursstab user in ILIAS can run a blind SQL injection via a whitelist bypass in the MyStaff lists and hijack an admin session.

Advisory ID: TP-2026-005
Product: ILIAS (open-source learning platform)
Vulnerability type: SQL injection (CWE-89)
CVE: pending
CVSS 3.1: 9.3 (Critical)
Fixed: in the current ILIAS releases (coordinated disclosure completed)
Reported: 23 April 2026

Summary

ILIAS is a widely used open-source learning platform (LMS). Through a whitelist bypass in the central table component, an attacker-controlled sort value reaches the ORDER BY of three MyStaff list queries unchecked. This is exploitable by any low-privileged user with an OrgUnit position (typical Kursstab or supervisor role), without administrator rights. turingpoint verified the end-to-end exploit as a time-based blind SQL injection against the current development branch.

Root cause

ilTable2GUI::determineOffsetAndOrder() sets nav_value directly from the attacker-controlled <prefix>_table_nav parameter (components/ILIAS/Table/classes/class.ilTable2GUI.php:1197). The in_array($order, $this->sortable_fields) whitelist only runs when nav_value is empty, so a set <prefix>_table_nav bypasses it and the order field is taken from the raw value (class.ilTable2GUI.php:1211-1230). ListUsers concatenates $options['sort']['field'] and ['direction'] into a raw ORDER BY of a query() call (components/ILIAS/MyStaff/classes/ListUsers/class.ilMStListUsers.php:84). The same unvalidated concatenation exists in ListCourses (class.ilMStListCourses.php:121) and ListCompetencesSkills (class.ilMStListCompetencesSkills.php:87). storeProperty() persists the manipulated sort value in the session, so the poisoned ORDER BY keeps firing on subsequent requests.

Proof of Concept

With a valid Kursstab session, a crafted myst_lu_table_nav parameter triggers a time-based blind injection on the MyStaff user list. Six managed employees times SLEEP(1) give around 6 s versus an instant baseline:

GET /ilias.php?baseClass=ilDashboardGUI&cmdNode=a4:kb:id&cmdClass=ilmstlistusersgui&cmd=index&myst_lu_table_nav=IF(1%3D1%2CSLEEP(1)%2C1)%3Aasc%3A0

Conditional comparisons read the global administrator's password-hash prefix character by character (SELECT ASCII(SUBSTRING(passwd,1,1)) FROM usr_data WHERE usr_id=6). Because the manipulated value is persisted via storeProperty(), the poisoned ORDER BY keeps firing on subsequent clean requests. sqlmap confirms the parameter as time-based blind injectable (current user: ilias@%, MariaDB 10.11).

Impact

  • Low-privileged Kursstab user gains full database read access: usr_data, usr_session, certificates, API tokens.
  • Reading usr_session directly yields the administrator's active session ID for immediate session takeover, without cracking any hash.
  • Admin takeover of the ILIAS instance from a low-privileged role.
  • The poisoned ORDER BY persists in the session and keeps firing until the user manually re-sorts.

References

Is Something Like This in Your Software?

Our team found this vulnerability in the course of its work. Have your applications tested by the same specialists, with a penetration test from turingpoint.