PHP 8.2 und WoltLab: Das SensitiveParameter-Attribut

Public Domain Image by the US Government

Jede moderne Software besteht zu Teilen aus wiederverwendbaren Software-Bibliotheken, um die Funktionalität bereitzustellen, so auch WoltLab Suite. Der Einsatz derartiger Software-Bibliotheken vermeidet es, das Rad neu zu erfinden, indem bestimmte, oftmals komplexe, Aufgaben an die Bibliothek ausgelagert werden, die von Experten des jeweiligen Fachgebiets entwickelt wurde und durch den vielfachen Einsatz auch in der Praxis erprobt ist.

Der Großteil der Software-Bibliotheken, die von WoltLab Suite genutzt werden, sind – genau wie WoltLab Suite Core, der Kern unserer eigenen Software – freie Software, die von den jeweiligen Entwicklern unter einer Open Source-Lizenz quelloffen und kostenfrei zur Verfügung gestellt werden. Der Einsatz freier Bibliotheken ermöglicht uns, die Bibliothek im Detail zu verstehen und etwaige Fehler auch selbst zu korrigieren. Fehler in unserer Software, die durch den Einsatz einer Software-Bibliothek verursacht werden, sind für den Kunden am Ende dennoch ein Fehler in unserer Software, der korrigiert werden muss.

Bei der Korrektur von Fehlern in eingesetzten Bibliotheken verfolgen wir aber eine sehr liberale „Upstreaming-Policy“: Fehler-Korrekturen und auch neue Funktionen geben wir wann immer möglich zurück an die Original-Bibliothek. Davon profitieren alle Beteiligten: Es entlastet die Entwickler der Bibliothek und gleichzeitig profitieren wir davon, dass unser Anwendungsfall beim Entwickler bekannt ist und bei einer zukünftigen Weiterentwicklung berücksichtigt werden kann.

Derartige Korrekturen und Verbesserungen haben wir bereits bei diversen Bibliotheken vorgenommen, aber noch nicht bei PHP selbst – bis jetzt. PHP 8.2 enthält zwei Verbesserungen, die von WoltLab entwickelt wurden: Eine größere neue Funktion und eine kleine Verbesserung.

„Redacting Parameters in Back Traces“

Die Problemstellung

Wann immer ein schwerwiegender Fehler in unserer Software auftritt, erscheint die bekannte Fehlerseite „An error has occurred“. Abhängig von den Einstellungen enthält diese Fehlerseite auch den sogenannten Stack Trace, der vereinfacht gesagt den Weg beschreibt, den die Software bei der Ausführung genommen hat, bis sie auf den Fehler gestoßen ist. Dieser Stack Trace enthält ebenfalls die Parameter, die an die genutzten Funktionen übergeben wurden und liefern für die Diagnose der Ursache wichtige Informationen. Aus diesem Grund ist es bei der Meldung von Fehlern wichtig, immer die vollständige Fehlermeldung, inklusive Stack Trace zu liefern, damit diese Informationen zur Verfügung stehen.

Unter Umständen können in den Daten des Stack Trace aber auch sensible Informationen wie Kennwörter enthalten sein. Beispielsweise erfordert der Verbindungsaufbau zur Datenbank die Übermittlung des Datenbankkennworts. Wenn die Verbindung aber nicht aufgebaut werden kann, weil beispielsweise der Datenbankserver kurzzeitig nicht erreichbar ist, dann würde normalerweise im erzeugten Stack Trace unweigerlich auch das Kennwort im Klartext als Parameter stehen.

Um sensible Daten im Stack Trace zu schützen, enthält WoltLab Suite daher bereits seit frühen Versionen eine Funktion, um den Stack Trace vorab zu bereinigen. Auf diese Weise konnten wir sicherstellen, dass Kennwörter für Datenbanken aus dem Stack Trace entfernt wurden, bevor diese gespeichert oder angezeigt wurden. Diese Bereinigung haben wir mit der Zeit erweitert und auf Parameter ausgedehnt, die – auf Basis der Benennung – möglicherweise sensible Daten enthalten.

Eine derartige Heuristik kann naturgemäß nicht alle möglichen Vorkommnisse zuverlässig erkennen und leidet damit am Phänomen „False Negatives“. Umgekehrt ist sie aber auch von „False Positives“ betroffen: Parameter werden irrtümlich als sensibel identifiziert und herausgefiltert. Wir waren entschlossen, das Problem an der Wurzel anzupacken und eine direkt in PHP integrierte Lösung zu entwickeln, um nicht nur unsere Software zuverlässig zu schützen, sondern auch andere Software, die auf PHP basiert und auf diese Weise die Sicherheit des Ökosystems im Ganzen zu verbessern.

Der „RFC“-Prozess zur Einreichung von Änderungen an PHP

Die Weiterentwicklung der PHP-Programmiersprache und die Integration neuer Funktionen erfolgt über den sogenannten „RFC-Prozess“. Ein RFC ist ein Dokument, in dem die vorgeschlagene Funktionalität präzise beschrieben wird. Im Gegensatz zu einem simplen „Wunsch“ für eine neue Funktion, werden bei einem RFC alle Aspekte und Auswirkungen der vorgeschlagenen Änderung genau beleuchtet, damit der Leser sich ein umfassendes Bild des Vorschlags machen kann.

Über die Mailingliste für die Weiterentwicklung von PHP (die sogenannte „PHP Internals“-Liste) wird der RFC vorgestellt und ermöglicht einen Austausch mit anderen Entwicklern, um eventuelle Probleme oder Unklarheiten zu beseitigen. Sobald der Diskussionsprozess abgeschlossen ist, kommt der RFC zur Abstimmung und muss von einer 2/3-Mehrheit akzeptiert werden, damit dieser in PHP einfließen kann. Stimmberechtigt sind PHP-Kernentwickler, die aktiv die Entwicklung von PHP vorantreiben, und auch erfahrene Entwickler, die sich seit längerem aktiv an den Diskussionen über neue RFCs beteiligen.

Für die Umsetzung haben wir uns für die mit PHP 8.0 eingeführten Attribute entschieden, mit denen es möglich ist, zusätzliche Daten für Klassen, Funktionen und eben auch Parameter zu hinterlegen:

PHP
function checkPassword(
    string $username,
    #[\SensitiveParameter] // Markiert den '$password'-Parameter mit der Information 'SensitiveParameter'
    string $password,
): bool {
  // …
}

Bevor wir dieses Konzept dann in Form des RFC-Dokuments beschrieben haben, haben wir zunächst die notwendigen Anpassungen an PHP programmiert, um das Konzept zu testen und zu prüfen, ob eine derartige Änderung technisch überhaupt praktikabel ist. Glücklicherweise war dies der Fall, sodass wir anschließend den RFC „Redacting Parameters in back traces“ (backtrace ist ein alternativer Name für Stack Trace) verfasst und Anfang Januar 2022 auf der Internals-Mailingliste zur Diskussion gestellt haben. Im Rahmen der Diskussion wurden wir auch von Derick Rethans eingeladen, im PHP Internals News-Podcast über den RFC zu sprechen und auf diese Weise die Hintergründe unseres Vorschlags noch näher zu erläutern.

Für Entwickler haben wir im Verlauf der Diskussion noch die Möglichkeit ergänzt, bei Bedarf explizit auf den Originalwert von bereinigten Parametern zugreifen zu können; Statt die Werte komplett zu entfernen, werden diese in eine Art „Schutzumschlag“ (eine Klasse namens SensitiveParameterValue) verpackt. Dieser „secure by default“-Ansatz stellt sicher, dass bei der normalen Verarbeitung von Stack Traces keine sensiblen Daten sichtbar sind, aber diese bei Bedarf durch die Software selbst weiterhin abgefragt werden können.

Mit dieser Änderung haben wir den RFC Anfang Februar zur Abstimmung freigegeben und konnten zwei Wochen später vermelden, dass unser Verbesserungsvorschlag mit einer Zustimmung von 96% für die Integration in PHP 8.2 akzeptiert wurde. Ab April haben wir in einem zweiten Schritt die direkt in PHP integrierten Funktionen bei sensiblen Parametern mit dem neuen Attribut ausgestattet, sodass jeder Nutzer von PHP ab Version 8.2 von einem Basisschutz sensibler Daten profitiert. Im weiteren Verlauf des Jahres wurde das neue Attribut auch schon von diversen PHP-Softwarebibliotheken in den eigenen Code integriert, um auch Nutzer dieser Bibliotheken zu schützen.

Auch die in Entwicklung befindliche WoltLab Suite 6.0 haben wir bereits angepasst, um eine bestmögliche Integration unseres RFCs zu ermöglichen. Unsere Funktion zum Bereinigen des Stack Trace berücksichtigt das neue Attribut auch in älteren PHP-Versionen, um einen bestmöglichen Schutz unserer Kunden zu ermöglichen. Auch findet die Heuristik zur Erkennung sensibler Parameter weiterhin Anwendung, falls noch nicht alle externen Bibliotheken angepasst worden sind.

Die Anzeige der Fehlermeldungen haben wir optisch überarbeitet, um sensible Parameter im Stack Trace besser kenntlich zu machen. Aus Sicherheitsgründen sind die entfernten Daten weder bei der Anzeige noch im Fehler-Protokoll enthalten.

An error message informing about a failed database connection. Sensitive information has been redacted.

Fazit

Das Konzept des RFC-Prozesses zur Weiterentwicklung von PHP war uns vor unserem ersten eigenen RFC durchaus bekannt, aber ohne ihn einmal selbst durchlaufen zu haben wirkte der Prozess sehr eindrucksvoll, da man einen Konsens unter vielen Entwicklern mit den unterschiedlichsten Kenntnissen, Erfahrungen und Meinungen finden muss. Die Integration unseres Vorschlags war auf ganzer Linie ein Erfolg und wir konnten PHP dadurch für jeden ein kleines bisschen besser machen.

Tatsächlich war das Ganze so erfolgreich, dass wir anschließend im Juli spontan noch einen zweiten, weniger umfangreichen RFC (Make the iterator_*() family accept all iterables) bei PHP eingereicht haben, der ebenfalls akzeptiert wurde. Auch haben wir uns auf der Internals-Mailingliste an der Diskussion über RFCs anderer Entwickler beteiligt, damit unsere eigenen Anforderungen und Wünsche Berücksichtigung finden.

Wir können jedem PHP-Entwickler empfehlen, die Diskussionen auf der Internals-Mailingliste zu verfolgen, sich aktiv zu beteiligen und möglicherweise auch einen eigenen RFC zu verfassen – die eigenen Wünsche und Meinungen können nur dann berücksichtigt werden, wenn man diese auch äußert.

Die Entwicklung von PHP 8.2 ist mit dem Feature Freeze im Juli und der Veröffentlichung vor einigen Tagen zu einem Abschluss gekommen. Wir werden uns aber auch in Zukunft weiter an der Entwicklung von PHP beteiligen und bei Bedarf neue RFCs verfassen.

Kommentare 6

Wird WSC 6.0 PHP 8.2 von Anfang an unterstützen? Wie lautet die Mindestanforderung? Ich bilde mir ein kurz in der Dokumentation 8.2 gelesen zu haben was jedoch zwischenzeitlich auf 8.1.2 geändert wurde. Kann ich mir aber auch eingebildet haben. LG

Ja, WoltLab Suite 6.0 ist bereits mit PHP 8.2 kompatibel und als kompatibel markiert. Darüber hinaus wird PHP 8.2 explizit die empfohlene Version zum Betrieb von WoltLab Suite 6.0 sein.

Ich verwende PHP 8.2 bereits seit Mitte des Jahres auf meinem Entwicklungssystem, sodass wir alle notwendigen Anpassungen frühzeitig vornehmen konnten. Eine Kompatibilität von WoltLab Suite 5.5 und PHP 8.2 können wir nicht herstellen, da die notwendigen Updates der Drittbibliotheken eine Anhebung der Systemanforderungen erfordern würden.

Die Mindestanforderung in der Dokumentation wurde von Anfang an mit PHP 8.1.2 angegeben, möglicherweise hast du dies beim Überfliegen als „8.2“ wahrgenommen: https://github.com/WoltLab/docs.w…9997e9a8c56b766

Das ist unglaublich beeindruckend <3

Ich habe davon zwar keine Ahnung, aber es liest sich so unglaublich spannend.

Charmant fand ich den Podcast, die englische Aussprache war süß :)

Wenn ich das richtig sehe, habt ihr sogar schon den 3. RFC eingereicht ;) https://wiki.php.net/rfc/randomizer_additions

Finde ich toll, dass ihr das gemacht habt. Davon werden wir auf jeden Fall profitieren.

Tatsächlich sind die „Randomizer Additions“ für mich schon Nummer 4 :) Nummer 3 und Nummer 4 sind aber im Wesentlichen privat, außerhalb der regulären Arbeitszeit, entstanden. Programmierung ist für mich am Ende auch ein Hobby und gerade die Programmierung in C ist ein spannender Kontrast zur regulären Arbeit. Die Grenze zwischen „Privatvergnügen“ und „Arbeit“ ist in Bezug auf PHP am Ende natürlich fließend, die „Randomizer Additions“ werden sicherlich auch irgendwann mal in WoltLab Suite zum Einsatz kommen, in den meisten Fällen reicht aber einfach ein Hex::encode(random_bytes(…)), sodass WoltLab Suite keinen unmittelbaren Nutzen daraus zieht.