1.Zusammenfassung

ILIAS kann Shibboleth als Anmeldeverfahren einbinden. Damit der Identity-Provider der Anwendung mitteilen kann, dass eine Sitzung beendet wurde, gibt es einen Rückkanal: einen Endpunkt, den nicht der Browser einer angemeldeten Person aufruft, sondern ein fremder Server. Dieser Endpunkt ist deshalb bewusst von der Anmeldepflicht ausgenommen – das ist an sich richtig, denn der Aufrufer ist niemand, der angemeldet sein könnte.

Um herauszufinden, welche Sitzung beendet werden soll, ging die Abmelde-Behandlung sämtliche noch laufenden Sitzungen der Instanz durch und übergab die jeweils gespeicherten Sitzungsdaten an eine eigene Zerlegefunktion. Diese rief unserialize() auf, ohne über den Parameter für zulässige Klassen einzuschränken, was dabei entstehen darf. Aus gespeicherten Zeichenketten wurden so echte Objekte – erzeugt im Auftrag eines Aufrufers, der sich nie angemeldet hat.

Der zweite Teil des Befunds ist die Frage, wie ein Angreifer überhaupt etwas in eine Sitzung bekommt. Auch das ging ohne Konto: Ein weiterer Einstiegspunkt der Anwendung, die LTI-Anbindung, legt übermittelte Anfrageparameter in der Sitzung ab und ist von derselben Initialisierung ebenfalls von der Anmeldepflicht ausgenommen. Damit lässt sich eine anonyme Sitzung mit beliebigem Inhalt anlegen, die anschließend in der Datenbank steht.

Beim Deserialisieren entstandene Objekte werden am Ende der Anfrage wieder verworfen, und dabei laufen ihre Aufräummethoden. Eine mit ILIAS ausgelieferte Bibliotheksklasse schreibt in ihrer Aufräummethode eine Datei, deren Pfad aus einer ihrer eigenen Eigenschaften stammt. Über diesen Weg konnte ein unangemeldeter Aufrufer eine Datei mit selbst bestimmtem Inhalt unterhalb des ausgelieferten Verzeichnisses ablegen und anschließend ausführen lassen – Codeausführung als Webserver-Benutzer, ohne Konto, ohne Token, ohne Zutun eines Menschen auf der Gegenseite.

2.Betroffene Systeme

Der verwundbare Code wurde in allen zum Zeitpunkt der Meldung gepflegten Versionslinien einzeln überprüft – nicht aus einer Linie auf die anderen geschlossen. Er ist in allen drei Linien vorhanden und in seiner Substanz identisch.

Betroffenheit je Versionslinie und der jeweils behebende Stand
Versionslinie Betroffen Behoben in
ILIAS 9 alle Stände vor 9.22 9.22
ILIAS 10 alle Stände vor 10.10 10.10
ILIAS 11 alle Stände vor 11.3 11.3

Vorhandener Code und tatsächliche Auslösbarkeit sind zweierlei

Die Versionsangaben oben folgen dem verwundbaren Code, und das ist für die Frage „muss ich aktualisieren?“ auch die richtige Grundlage. Bei der Prüfung der einzelnen Linien hat sich allerdings gezeigt, dass sich der Endpunkt nicht überall gleich verhält. Ich halte das hier fest, weil es Betreibern bei der Priorisierung hilft – nicht, weil es die Dringlichkeit des Updates verringert:

Verhalten des Endpunkts im jeweils ausgelieferten Zustand
Linie Verwundbarer Code Über den Endpunkt auslösbar
ILIAS 9 vorhanden Nein. Der zuständige Zweig hängt an einer Superglobalen, die es seit PHP 7 nicht mehr gibt; er wird deshalb nie betreten.
ILIAS 10 vorhanden Ja – im Rahmen der Meldung nachgewiesen.
ILIAS 11 vorhanden Nein. Der Endpunkt greift auf den Dienst-Container zu, bevor dieser aufgebaut wird, und bricht deshalb bei jeder Anfrage vorher ab.

Kein Grund, das Update aufzuschieben

Was den Endpunkt in den Linien 9 und 11 blockiert, sind Nebenumstände: eine Sprachänderung in PHP und ein Programmierfehler an anderer Stelle. Beides sind Eigenschaften des ausgelieferten Zustands, keine Schutzmaßnahmen. Ein Patch, ein Plugin oder eine angepasste Installation können sie aufheben, ohne dass das jemandem auffällt. Der verwundbare Code selbst ist in allen drei Linien vorhanden – und deshalb hat der Hersteller ihn auch in allen drei entfernt.

Wann eine Instanz praktisch erreichbar war

Über die Version hinaus hängt die tatsächliche Ausnutzbarkeit an Eigenschaften der Betriebsumgebung. Für die Einschätzung der eigenen Installation sind vor allem relevant: ob die SOAP-Erweiterung von PHP geladen ist, ob der Endpunkt für den Server selbst über HTTPS mit einem ihm vertrauenswürdigen Zertifikat erreichbar ist, und ob unterhalb des ausgelieferten Verzeichnisses ein beschreibbarer Bereich liegt, in dem abgelegte Dateien auch ausgeführt werden. In einer Standardinstallation sind diese Bedingungen erfüllbar; wer seine Instanz abweichend betreibt, war unter Umständen nicht erreichbar. Auch das ist eine Momentaufnahme der Konfiguration und kein Ersatz für das Update.

3.Technische Analyse

Voraussetzungen. Keine. Kein Konto, keine Rolle, kein CSRF-Token, keine Interaktion auf der Gegenseite. Ausreichend waren zwei gewöhnliche HTTP-Anfragen an Endpunkte, die beide öffentlich erreichbar sein müssen, damit die zugehörigen Verfahren funktionieren.

Der Befund entsteht nicht an einer einzelnen Stelle. Er entsteht dort, wo zwei Entscheidungen aufeinandertreffen, die jede für sich nachvollziehbar sind: ein Endpunkt, der ohne Anmeldung erreichbar sein muss, und ein Speicher, den ein Unangemeldeter befüllen kann. Dazwischen liegt eine Funktion, die diesen Speicher als vertrauenswürdig behandelt.

Die vier Glieder

  1. Der Endpunkt ist von der Anmeldepflicht ausgenommen Die zentrale Initialisierung von ILIAS kennt Kontexte, in denen keine Authentifizierung verlangt wird. Der Shibboleth-Rückkanal ist einer davon, und das zu Recht: Der aufrufende Identity-Provider ist kein angemeldeter Benutzer.
  2. Die Abmelde-Behandlung liest alle Sitzungen Um die zu beendende Sitzung zu bestimmen, wurden sämtliche noch gültigen Sitzungsdatensätze geladen und ihre gespeicherten Inhalte einzeln durch eine selbstgeschriebene Zerlegefunktion geschickt.
  3. Deserialisierung ohne Klassenbeschränkung Diese Funktion rief unserialize() ohne Angabe zulässiger Klassen auf. Damit entsteht aus dem gespeicherten Text jedes beliebige Objekt, dessen Klasse die Anwendung kennt – einschließlich der Klassen aus mitgelieferten Fremdbibliotheken.
  4. Der Inhalt kam ohne Anmeldung in die Sitzung Ein weiterer, ebenfalls anmeldefreier Einstiegspunkt legt übermittelte Anfrageparameter in der Sitzung ab. Die so erzeugte anonyme Sitzung wird gespeichert – und damit vom Schritt zuvor mitgelesen.

Warum ist das gefährlich, wenn doch nur gelesen wird?

unserialize() liest keine Daten, es baut Objekte. Diese Objekte gehören zu echten Klassen der Anwendung, und ihre Lebenszyklus-Methoden laufen – auch dann, wenn das Programm sie nie benutzt, denn spätestens beim Verwerfen wird die Aufräummethode aufgerufen. Ein gewachsenes Projekt bringt über seine Abhängigkeiten fast immer eine Klasse mit, die dabei etwas Folgenreiches tut: eine Datei schreiben, einen Befehl absetzen, eine Verbindung öffnen. Der Angreifer schreibt also keinen Code, sondern setzt vorhandene Bausteine so zusammen, dass ihr normales Verhalten das Gewünschte bewirkt. Deshalb lautet die Regel ohne Ausnahme: unserialize() nie auf Daten anwenden, die von außen beeinflusst werden können – und wenn es unvermeidlich ist, die zulässigen Klassen ausdrücklich einschränken.

Zurückgehalten

Anders als in SIT-2026-001 zeige ich hier keinen Quelltext, benenne die als Werkzeug geeignete Bibliotheksklasse nicht und stelle den Ablauf nicht als Abfolge konkreter Anfragen dar. Bei einer Codeausführung ohne Anmeldung, deren Patch wenige Wochen alt ist, wäre das eine Bauanleitung gegen jede Instanz, die noch nicht aktualisiert wurde. Wer den Code lesen möchte, findet ihn über den in Abschnitt 7 verlinkten Commit des Herstellers.

Der Fix des Herstellers

Der Hersteller hat die Abmelde-Behandlung des Endpunkts in allen drei Linien entfernt, statt sie abzusichern. Das halte ich für die richtige Entscheidung: Die Funktion war an eine Betriebsart gebunden, die nur ein Teil der Instanzen überhaupt nutzt, und ihre Aufgabe – aus einer fremden Mitteilung die passende lokale Sitzung heraussuchen – lässt sich ohne das Durchsehen aller Sitzungsdaten kaum sinnvoll lösen. Entfernter Code ist der einzige, der garantiert keine Lücken mehr enthält.

Warum die Kette gehalten hat

Auch hier ist keiner der Punkte für sich genommen ein Fehler. Erst ihr Zusammentreffen ergibt den Befund:

  • Eine Ausnahme von der Anmeldepflicht, die für ihren ursprünglichen Zweck richtig ist, gilt für alles, was in diesem Kontext läuft – auch für später hinzugekommene Verarbeitung.
  • Dieselbe Initialisierung nimmt einen zweiten Einstiegspunkt von der Anmeldepflicht aus, der Daten schreibt. Für sich betrachtet harmlos, in Kombination die halbe Miete.
  • Sitzungsdaten gelten in vielen Anwendungen implizit als vertrauenswürdig, weil sie „von uns selbst“ stammen. Sobald ein anmeldefreier Pfad hineinschreiben kann, stimmt diese Annahme nicht mehr.
  • Die Zerlegefunktion war handgeschrieben und deserialisierte ohne Klassenbeschränkung – der Parameter dafür existiert seit PHP 7.0.
  • Die Verarbeitung betraf alle Sitzungen der Instanz, nicht nur die des Aufrufers. Damit genügte es, überhaupt irgendwo eine Sitzung anzulegen.
  • Über die mitgelieferten Fremdbibliotheken stand eine Klasse zur Verfügung, deren normales Verhalten beim Aufräumen das Schreiben einer Datei ist.

4.Auswirkung (Impact)

Am Ende der Kette steht Codeausführung mit den Rechten des Webserver-Benutzers. Damit ist nicht eine einzelne Funktion betroffen, sondern die gesamte Instanz: alle Inhalte und Kurse, alle Benutzerkonten samt Passwort-Hashes, der vollständige Datenbestand, hinterlegte Zugangsdaten zu angebundenen Systemen sowie sämtliche laufenden Sitzungen. Ab diesem Punkt ist die Installation nicht mehr vertrauenswürdig, und der eingespielte Patch allein macht sie es auch nicht wieder.

Erschwerend kommt hinzu, dass es keine Hürde gibt, die einen Angreifer aufhält: Ohne Konto und ohne Nutzerinteraktion lässt sich der Ablauf automatisieren und breit gegen erreichbare Instanzen fahren, sobald die Stelle bekannt ist. Genau das ist der Unterschied zu SIT-2026-001, wo immerhin ein angemeldetes Konto mit Schreibrecht nötig war.

Begründung der wesentlichen CVSS-4.0-Metriken
Metrik Wert Begründung
Angriffsvektor Netzwerk Gewöhnliche HTTP-Anfragen an öffentlich erreichbare Endpunkte.
Komplexität niedrig Kein Raten, kein Zeitfenster, keine Umgehung einer Schutzmaßnahme.
Benötigte Rechte keine Beide beteiligten Endpunkte sind von der Anmeldepflicht ausgenommen.
Nutzerinteraktion keine Es muss niemand auf etwas klicken oder angemeldet sein.
Vertraulichkeit / Integrität / Verfügbarkeit jeweils hoch Codeausführung als Webserver-Benutzer umfasst Lesen, Verändern und Zerstören.

Zur Einordnung gehört die Gegenprobe: Die Bewertung setzt voraus, dass die in Abschnitt 2 genannten Umgebungsbedingungen erfüllt sind. Sie beschreiben eine gewöhnliche Installation, aber nicht jede. Ich führe sie ausdrücklich auf, damit Betreiber die eigene Lage beurteilen können, statt einer Zahl vertrauen zu müssen – und weil eine Bedingung, die heute nicht erfüllt ist, morgen erfüllt sein kann.

Auswirkung in einem Satz: Vollständige Übernahme der Instanz durch einen beliebigen Aufrufer aus dem Netz, ohne Konto und ohne Zutun eines Menschen auf der Gegenseite.

5.Gegenmaßnahmen / Workarounds

Update

Die maßgebliche und einzige vollständige Maßnahme ist das Update auf ILIAS 9.22, 10.10 oder 11.3. Die Versionen wurden am 12.08.2026 bereitgestellt und enthalten neben dieser Korrektur weitere Sicherheitsbehebungen.

Überbrückung, wenn nicht sofort aktualisiert werden kann

  • Den Endpunkt am vorgelagerten Webserver sperren. Betroffen ist shib_logout.php aus der Shibboleth-Komponente (der Pfad unterscheidet sich zwischen den Versionslinien; der öffentliche CVE-Eintrag nennt ihn vollständig). Wer Shibboleth nicht als Anmeldeverfahren nutzt, braucht diesen Rückkanal nie – Anfragen darauf können ohne Nebenwirkung abgewiesen werden, und das ist die wirksamste Sofortmaßnahme. Wer Shibboleth nutzt, kann den Zugriff auf die Adressen des eigenen Identity-Providers einschränken.
  • Nicht genutzte Einstiegspunkte ebenfalls sperren. Das gilt insbesondere für den Einstiegspunkt der LTI-Anbindung, wenn keine externen Werkzeuge angebunden sind. Er ist der Weg, über den Inhalte ohne Anmeldung in eine Sitzung gelangen, und in einer typischen Installation ebenso ungenutzt wie erreichbar.
  • Ausführung im Datenverzeichnis unterbinden. Dass unterhalb des ausgelieferten Verzeichnisses abgelegte Dateien vom Webserver ausgeführt werden können, ist unabhängig von diesem Befund eine lohnende Härtung – und hier das Glied, das aus dem Schreiben einer Datei eine Codeausführung macht.

Bei dieser Schwachstelle genügt Patchen nicht

Wurde die Lücke ausgenutzt, bevor das Update eingespielt wurde, bleibt der Zugang des Angreifers bestehen – abgelegte Dateien, veränderte Konten oder hinterlegte Schlüssel verschwinden durch ein Update nicht. Vor der Entwarnung steht deshalb die Prüfung im nächsten Abschnitt.

Prüfung auf zurückliegende Ausnutzung

Beide beteiligten Endpunkte werden über gewöhnliche HTTP-Anfragen angesprochen und hinterlassen entsprechende Spuren. Sinnvolle Ansatzpunkte:

  • Zugriffe auf shib_logout.php. In Instanzen ohne Shibboleth sollte es sie überhaupt nicht geben; jeder einzelne Treffer ist erklärungsbedürftig. In Instanzen mit Shibboleth sind Aufrufe von anderen Adressen als denen des eigenen Identity-Providers auffällig.
  • Neue oder veränderte ausführbare Dateien unterhalb des ausgelieferten Datenverzeichnisses – abgeglichen gegen den Stand einer bekannt sauberen Sicherung, nicht nach Gefühl.
  • Ungewöhnlich große Sitzungsdatensätze in der Sitzungstabelle, insbesondere solche ohne zugeordnetes Benutzerkonto.
  • PHP-Fehler im Zusammenhang mit der SOAP-Verarbeitung oder mit dem Deserialisieren, die zeitlich mit solchen Aufrufen zusammenfallen.

Verdichtet sich der Verdacht, ist die Instanz als kompromittiert zu behandeln: vom Netz nehmen, Beweise sichern, aus einer nachweislich sauberen Sicherung neu aufsetzen, alle Zugangsdaten und Schlüssel erneuern – auch die zu angebundenen Systemen – und sämtliche Sitzungen invalidieren. Ein Zurücksetzen der Passwörter allein genügt nicht, wenn der Angreifer Code auf dem Server ausführen konnte.

Hinweis für Betreiber

Bei Fragen zur Betroffenheit der eigenen Installation oder zur Auswertung von Protokolldaten können Sie sich an security@schweigertit.de wenden.

6.Disclosure-Timeline

  1. Identifikation und Meldung an den Hersteller Mantis 0048152
  2. Patch durch den Hersteller ILIAS 9.22, 10.10 und 11.3
  3. Veröffentlichung des CVE-Eintrags CVE-2026-80428
  4. Veröffentlichung dieses Advisories

7.Referenzen

  • CVE CVE-2026-80428 – veröffentlicht am 26.08.2026, CWE-502, CVSS 4.0 9.3 (Critical).
  • Hersteller ILIAS open source e-Learning e.V. – Meldung vom 03.08.2026, erfasst als Mantis 0048152; Korrektur enthalten in den Releases 9.22, 10.10 und 11.3 vom 12.08.2026.
  • Korrektur Commit f36934a6f937d0fe837ca6e642986458b4069a95 im Repository des Herstellers.
  • CWE CWE-502 – Deserialisierung nicht vertrauenswürdiger Daten.
  • Verwandt SIT-2026-001 – zweiter Befund aus derselben Untersuchung, behoben in denselben Releases.
  • Policy Richtlinie zur verantwortungsvollen Offenlegung von schweigertIT.
  • Research Research-Übersicht mit der laufenden CVE-Liste.

Rückfragen zu diesem Advisory

Fragen richten Sie bitte an security@schweigertit.de, gerne verschlüsselt. Proof-of-Concept-Code gebe ich auch auf Anfrage nicht heraus.

Writeup zur PHP-Objektinjektion in der Reihe „Poking on ILIAS“

Verantwortungsvolle Offenlegung

Warum hier weniger steht als sonst

Bei SIT-2026-001 konnte ich den Quelltext zeigen und den Weg des Werts Glied für Glied nachzeichnen, weil dort ein angemeldetes Konto nötig war und die Korrektur unmittelbar einleuchtet. Hier liegt der Fall anders: Eine Codeausführung ohne Anmeldung ist automatisiert gegen jede erreichbare Instanz einsetzbar, und nach einem Patch dauert es Wochen bis Monate, bis die Mehrheit der Installationen aktualisiert ist.

Deshalb steht hier genau so viel, wie Betreiber brauchen, um ihre Betroffenheit zu beurteilen, richtig zu priorisieren und Protokolldaten auszuwerten – und nichts, was jemandem die Arbeit abnimmt, der eine ungepatchte Instanz sucht. Diese Abwägung nehme ich bei jeder Veröffentlichung neu vor; sie fällt nicht immer gleich aus.