Cronicle: Stored XSS im Admin-Aktivitätsprotokoll über das full_name-Feld

Ein nicht-privilegierter Nutzer setzt sein eigenes full_name-Feld auf ein XSS-Payload, das beim Öffnen des Aktivitätsprotokolls in der Administrator-Sitzung ausgeführt wird.

Advisory-ID: TP-2026-021
Produkt: Cronicle (Multi-Server-Taskplaner und -Runner mit Web-Oberfläche)
Schwachstellentyp: Stored Cross-Site-Scripting (CWE-79)
CVE: CVE-2026-55562
CVSS 3.1: 9.0 (Kritisch) · CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H
Betroffene Versionen: <= 0.9.118
Behoben in: 0.9.119
Hersteller-Advisory: GHSA-vh39-3pcm-2j63
Gemeldet: 13. Juni 2026

Zusammenfassung

Cronicle ist ein Multi-Server-Taskplaner mit Web-Oberfläche. Das Admin-Aktivitätsprotokoll fügt das vom Nutzer kontrollierte full_name-Feld eines Kontos roh in die Zeilenbeschreibung ein und schreibt das zusammengesetzte Markup per jQuery .html() in das DOM, ohne es zu kodieren. Der einzige eingangsseitige Schutz ist ein Filter replace(/<.+>/g,''), dessen Punkt-Metazeichen keinen Zeilenumbruch trifft, sodass ein <img>-Tag mit eingebettetem Zeilenumbruch den Filter passiert und ein gültiges HTML-Element bleibt. Das Setzen des eigenen full_name erfordert nur eine gültige Sitzung plus das aktuelle Passwort und keinerlei Privileg, sodass jeder authentifizierte Nicht-Admin (oder bei free_accounts:true ein anonymer Selbstregistrant) das Payload platziert. Cronicle liefert keine Content-Security-Policy aus, und das Payload wird in der Sitzung des Administrators ausgeführt, sobald dieser das Aktivitätsprotokoll öffnet. Das ergibt eine Privilegienerhöhung vom Nicht-Admin zum Admin und über das Shell-Plugin Befehlsausführung als Cronicle-Dienstkonto. turingpoint hat den Ablauf verifiziert und verantwortungsvoll gemeldet; der Hersteller hat ihn in 0.9.119 behoben.

Ursache

Der Renderer fügt das angreiferkontrollierte item.user.full_name roh in das Zeilen-Markup ein und schreibt es per jQuery this.div.html(html) (htdocs/js/pages/admin/Activity.js:142/146/150/154, Senke :243), während das benachbarte item.description-Feld über encode_entities escaped wird (:214/221). Der einzige eingangsseitige Schutz ist user.full_name.replace(/<.+>/g,'') in node_modules/pixl-server-user/user.js:485, doch das Punkt-Metazeichen trifft keinen Zeilenumbruch, sodass <img src=x\nonerror=alert(document.domain)> den Strip übersteht und ein gültiges HTML-Element bleibt. Das full_name-Feld wird ansonsten nur gegen /\S/ validiert (user.js:90), sodass keine weitere Zeichenklasse das Payload blockiert. Das Setzen des eigenen full_name über POST /api/user/update verlangt nur eine gültige Sitzung plus das aktuelle Passwort und kein Privileg (api_update, user.js:421), sodass jeder authentifizierte Nicht-Admin (oder bei free_accounts:true ein anonymer Selbstregistrant) es platziert. Cronicle liefert standardmäßig keine Content-Security-Policy aus, und das Payload feuert in der Sitzung des Administrators, sobald dieser das requireAdmin-geschützte Aktivitätsprotokoll öffnet (lib/api/admin.js:25).

Proof of Concept

Als authentifizierter Nicht-Admin (Zeilenumbruch als JSON \n kodiert):

POST /api/user/update HTTP/1.1
Content-Type: application/json

{"session_id":"<Nicht-Admin-Sitzung>","username":"lowuser","full_name":"<img src=x\nonerror=alert(document.domain)>","old_password":"<aktuelles Passwort>"}

Der Zeilenumbruch im <img>-Tag umgeht den /<.+>/g-Strip, der Wert wird byte-genau gespeichert und roh im Admin-Feed get_activity zurückgegeben. Öffnet der Administrator das Aktivitätsprotokoll, parst this.div.html() den Wert zu einem lebenden Element, dessen onerror-Handler in der Admin-Sitzung feuert.

Auswirkung

  • Ausführung beliebigen JavaScripts in der Sitzung des Administrators, sobald dieser das Aktivitätsprotokoll öffnet; keine weitere Interaktion nötig.
  • Privilegienerhöhung von jedem authentifizierten Nicht-Admin zum Admin: neue Admin-Konten und API-Keys lassen sich aus der Opfer-Sitzung anlegen.
  • Befehlsausführung als Cronicle-Dienstkonto (root im Standard-Container-Image) über das Shell-Plugin.
  • Bei gesetztem free_accounts:true durch einen anonymen Selbstregistranten ausnutzbar.

Referenzen

Steckt so etwas in Ihrer Software?

Diese Schwachstelle hat unser Team im Rahmen seiner Arbeit gefunden. Lassen Sie Ihre Anwendungen von denselben Spezialisten prüfen, mit einem Penetrationstest von turingpoint.