PhpSpreadsheet CVE-2026-45034: Drei Slashes hebeln den Phar-Wrapper-Schutz aus — Patch-Bypass für CVE-2026-34084 mit RCE-Potential
CVE-2026-45034 (GHSA-87m4-826x-3crx, CVSS 4.0 9.2, CWE-502) ist ein vollständiger Bypass des Phar-Wrapper-Schutzes, den PhpSpreadsheet als Reaktion auf CVE-2026-34084 eingeführt hatte. Der Schutzmechanismus File::prohibitWrappers() prüft Dateinamen auf gefährliche Stream-Wrapper-Schemata wie phar:// — verlässt sich dabei aber auf das Rückgabeverhalten von PHPs parse_url(). Bei Pfaden mit drei oder mehr Slashes nach dem Schema, etwa phar:///pfad/exploit.phar/dummy.csv, liefert parse_url()false statt eines Schema-Strings zurück — die Prüfung wird dadurch komplett umgangen, während PHPs Stream-Layer die URI weiterhin korrekt als Phar-Wrapper auflöst. Auf PHP 7.x kann das zur automatischen Deserialisierung von Phar-Metadaten und damit zu Remote Code Execution über Object-Injection-Gadget-Chains führen, auf PHP 8.x zu einer Datei-Lese-Primitive. Betroffen sind PhpSpreadsheet-Versionen bis einschließlich 1.30.4, gefixt in der am 07.06.2026 veröffentlichten Version 1.30.5.
TL;DR — 90 Sekunden
- Betroffen?
Jedes PHP-Projekt mit
phpoffice/phpspreadsheet≤ 1.30.4 als Composer-Abhängigkeit, das Dateinamen — direkt oder indirekt — aus Nutzereingaben anIOFactory::load()oder verwandte Lesefunktionen übergibt.- Risiko?
Vollständiger Bypass des Phar-Wrapper-Schutzes aus CVE-2026-34084 (CVSS 4.0 9.2, CWE-502). Auf PHP 7.x potenziell Remote Code Execution über Phar-Deserialisierung und Object-Injection-Gadget-Chains, auf PHP 8.x eine Datei-Lese-Primitive.
- Sofortmaßnahme?
composer require phpoffice/phpspreadsheet:^1.30.5— oder, falls ein Update kurzfristig nicht möglich ist, jede Dateiname-Eingabe vor der Verarbeitung explizit auf das Substring://prüfen und ablehnen.- Empfehlung?
Composer-Abhängigkeitsbaum auf transitive Nutzung von PhpSpreadsheet prüfen (z. B. über Reporting-/Export-Bundles),
phar.readonlyexplizit aufOnsetzen und Datei-Uploads grundsätzlich per Extension-Allowlist statt Blocklist filtern.- Kritikalität?
hoch — hoher CVSS-Wert, öffentlich dokumentierter Bypass-Mechanismus und Proof-of-Concept-Code vorhanden, aber keine bislang bekannte aktive Ausnutzung in freier Wildbahn und Erfolg abhängig von PHP-Version,
phar.readonly-Konfiguration und Erreichbarkeit eines nutzbaren Gadget-Chains.
Was ist das Problem?
PhpSpreadsheet ist die de-facto-Standardbibliothek für das Lesen und Schreiben von Excel-, CSV- und ODS-Dateien in PHP — sie steckt direkt oder über Wrapper-Pakete in einer großen Zahl von PHP-Frameworks, CMS-Erweiterungen und Business-Anwendungen, überall dort, wo Nutzer Tabellen hoch- oder herunterladen können. Im Mai 2026 wurde mit CVE-2026-34084 eine Schwachstelle bekannt, bei der über den phar://-Stream-Wrapper eingeschleuste Dateien zur Deserialisierung von Phar-Metadaten und damit potenziell zu Remote Code Execution führen konnten. Als Reaktion führten die Maintainer die Methode File::prohibitWrappers() ein, die Dateinamen vor der Verarbeitung auf gefährliche Schemata wie phar://, php:// oder zip:// prüfen soll.
CVE-2026-45034 zeigt, dass dieser Schutz sich vollständig umgehen lässt. Der Grund liegt in einer Eigenheit von PHPs eingebauter Funktion parse_url(): Enthält eine URL drei oder mehr Slashes direkt nach dem Schema-Doppelpunkt — etwa phar:///pfad/exploit.phar/dummy.csv — interpretiert parse_url() diese Struktur als ungültig und liefert false zurück, statt wie erwartet den String "phar" als Schema zu extrahieren. Der Validierungscode in prohibitWrappers() prüft anschließend mit is_string($scheme), ob überhaupt ein Schema erkannt wurde — bei false ist das nicht der Fall, die Prüfung wird komplett übersprungen und der Dateiname als unbedenklich durchgelassen.
Das Problem: PHPs zugrunde liegende Stream-Layer verwendet eine eigene, robustere URI-Auflösung und interpretiert denselben Pfad trotzdem korrekt als phar://-Wrapper-Zugriff. Die Diskrepanz zwischen der (fehlerhaften) Validierungslogik und dem tatsächlichen Verhalten der Stream-Schicht ist der Kern des Bypasses: Was für prohibitWrappers() wie ein gewöhnlicher Dateiname aussieht, wird von PHP selbst weiterhin als Phar-Archiv geöffnet — inklusive automatischer Verarbeitung der darin enthaltenen, vom Angreifer kontrollierten serialisierten Metadaten.
Wer ist betroffen?
| Betroffen | Nicht betroffen / unklar | Bedingungen |
|---|---|---|
Projekte mit phpoffice/phpspreadsheet in Version ≤ 1.30.4 (direkt oder als transitive Abhängigkeit eines Report-/Export-Pakets) | Projekte, die bereits auf 1.30.5 oder neuer aktualisiert haben | Composer-Lockfile prüfen — auch bei indirekter Einbindung über andere Pakete |
Code-Pfade, die einen (auch nur teilweise) nutzerkontrollierten Dateinamen oder Upload-Pfad an IOFactory::load(), IOFactory::createReaderForFile() oder ähnliche Lesefunktionen übergeben | Rein interne Verarbeitung fester, nicht nutzerkontrollierter Dateipfade ohne jegliche Upload- oder URL-Eingabe | Auch serverseitig generierte, aber aus Nutzereingaben zusammengesetzte Pfade zählen als nutzerkontrolliert |
| PHP-7.x-Umgebungen für das volle RCE-Potenzial über Phar-Objektinjektion | PHP-8.x-Umgebungen sind laut aktueller öffentlicher Analyse auf eine Datei-Lese-Primitive beschränkt — weiterhin ernst, aber kein automatischer RCE-Pfad | Die tatsächliche Auswirkung auf PHP 8.x hängt zusätzlich von phar.readonly und im Autoloader erreichbaren Gadget-Klassen ab |
Die Schwachstelle wurde am 07.06.2026 über die GitHub Advisory Database als GHSA-87m4-826x-3crx mit CVSS 4.0 9.2 (Kritisch, CWE-502) veröffentlicht. Eine bestätigte Ausnutzung in freier Wildbahn ist nach aktuellem Kenntnisstand nicht dokumentiert, allerdings existiert öffentlich einsehbarer Proof-of-Concept-Code zu dieser CVE — die technischen Details des Bypasses sind vollständig öffentlich, was das Risiko einer kurzfristigen Ausnutzung erhöht.
Auswirkungen
Auf PHP 7.x eröffnet der Bypass den klassischen Phar-Deserialisierungs-Angriffspfad: Wird eine vom Angreifer präparierte .phar-Datei über einen Dateinamen mit dem beschriebenen Drei-Slash-Muster an PhpSpreadsheet übergeben, verarbeitet PHP beim Zugriff automatisch die im Phar-Stub enthaltenen serialisierten Metadaten — unabhängig davon, ob die Anwendung tatsächlich eine Tabellenkalkulationsdatei erwartet oder einliest. Enthält der Autoloader der Zielanwendung geeignete Klassen mit ausnutzbaren __wakeup()- oder __destruct()-Methoden (ein sogenannter Gadget-Chain), kann daraus Remote Code Execution mit den Rechten des PHP-Prozesses entstehen — in vielen Deployments also mit Zugriff auf Datenbank-Credentials, API-Keys und das Dateisystem der Anwendung.
Auf PHP 8.x ist die unmittelbare Auswirkung nach aktuellem öffentlichem Kenntnisstand auf eine Datei-Lese-Primitive begrenzt — der Bypass erlaubt weiterhin, dass PhpSpreadsheet Inhalte außerhalb des erwarteten Datei-Kontexts liest, was je nach Anwendung zum Auslesen von Konfigurationsdateien, Credentials oder anderen sensiblen Dateien auf dem Server führen kann. Da PhpSpreadsheet häufig in Export-/Import-Funktionen von Admin-Backends, Reporting-Modulen und Datenmigrations-Workflows eingesetzt wird — Kontexten, die ohnehin bereits erhöhte Rechte und Zugriff auf sensible Daten haben — ist der potenzielle Blast-Radius eines erfolgreichen Angriffs unabhängig von der PHP-Version relevant.
Mitigation / Sofortmassnahmen
Operativer Entscheidungsblock
- Heute handeln, wenn … Ihre Anwendung Datei-Uploads oder nutzerbeeinflusste Dateinamen an PhpSpreadsheet-Lesefunktionen übergibt und noch auf Version ≤ 1.30.4 läuft.
- Mit Priorität prüfen, wenn … PhpSpreadsheet nur transitiv über ein Reporting- oder Export-Paket eingebunden ist — die Versionsbindung ist dann leicht zu übersehen.
- Nur beobachten, wenn … Ihre Anwendung PhpSpreadsheet ausschließlich auf feste, serverseitig generierte Dateipfade ohne jegliche Nutzereingabe anwendet.
Schritt 1 — Auf die gefixte Version aktualisieren
# Composer-Update auf die gefixte Version
composer require phpoffice/phpspreadsheet:^1.30.5
# Pruefen, welche Version tatsaechlich installiert ist
composer show phpoffice/phpspreadsheet | grep -i versions
# Falls PhpSpreadsheet nur transitiv eingebunden ist:
composer why phpoffice/phpspreadsheet
Schritt 2 — Kurzfristige Kompensation, falls ein Update nicht sofort moeglich ist
# Eingabevalidierung VOR jedem IOFactory::load()-Aufruf:
# Dateinamen mit dem Substring "://" grundsaetzlich ablehnen,
# unabhaengig von parse_url()-Ergebnissen
if (str_contains($filename, '://')) {
throw new InvalidArgumentException('Ungueltiger Dateiname');
}
# Zusaetzlich: nur erwartete Dateiendungen zulassen (Allowlist, keine Blocklist)
$allowed = ['xlsx', 'xls', 'csv', 'ods'];
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
if (!in_array($ext, $allowed, true)) {
throw new InvalidArgumentException('Dateityp nicht erlaubt');
}
Schritt 3 — PHP-Konfiguration haerten
# phar.readonly explizit erzwingen (verhindert das Schreiben neuer Phar-Archive,
# schuetzt aber allein NICHT vor dieser Deserialisierungs-Bypass-Kette)
php -i | grep phar.readonly
# in php.ini explizit setzen:
# phar.readonly = OnDetection / Prüfung
Installierte Version und Nutzung pruefen
# Direkte Abhaengigkeit?
grep -A2 '"phpoffice/phpspreadsheet"' composer.lock
# Transitive Abhaengigkeit ueber welches Paket?
composer why phpoffice/phpspreadsheet
# Codebasis nach direkten IOFactory-Aufrufen durchsuchen
grep -rn "IOFactory::load(\|IOFactory::createReaderForFile(" --include="*.php" .
Verdaechtige Dateinamen/Pfade in Logs und Uploads suchen
# Access-/Application-Logs auf das Drei-Slash-Muster durchsuchen
grep -E "phar:///" /var/log/*/access.log storage/logs/*.log 2>/dev/null
grep -E "[a-z]+:/{3,}" storage/logs/*.log 2>/dev/null
# Upload-Verzeichnisse auf .phar-Dateien mit ungewoehnlichen Namen pruefen
find /path/to/uploads -iname "*.phar*" -o -iname "*phar*"
Laufzeit-Indikatoren
- Datei-Upload- oder Import-Requests mit Dateinamen, die das Substring
://enthalten — in einem regulären Excel-/CSV-Upload sollte das nie vorkommen - Unerwartete PHP-Fehler oder -Warnungen im Zusammenhang mit
unserialize()oder Phar-Verarbeitung kurz nach einem Datei-Upload - Ungewöhnliche ausgehende Verbindungen oder Prozessstarts direkt im Anschluss an einen Datei-Import-Request
Betreiberempfehlung
Mid-Market
Composer-Lockfile auf phpoffice/phpspreadsheet prüfen — auch bei nur transitiver Einbindung über Report- oder Export-Pakete — und zeitnah auf 1.30.5 aktualisieren. Wo ein sofortiges Update nicht möglich ist, die beschriebene Eingabeprüfung auf das Substring :// als Kompensation vorschalten.
Enterprise
Zusätzlich: alle Codepfade identifizieren, die nutzerkontrollierte Dateinamen an PhpSpreadsheet oder ähnliche Datei-Verarbeitungsbibliotheken übergeben, und diese Verarbeitung nach Möglichkeit in isolierten Workern mit minimalen Rechten und ohne Zugriff auf produktive Credentials ausführen. phar.readonly in allen Umgebungen explizit auf On setzen und PHP-Versionen mit Blick auf PHP-7.x-Restbestände inventarisieren — dort ist das RCE-Potenzial am größten.
Alle Composer-Projekte mit Datei-Uploads
Unabhängig von PhpSpreadsheet: Dieser Fall ist ein gutes Beispiel dafür, dass Validierung auf Basis von parse_url() allein nicht ausreicht, um Stream-Wrapper-Missbrauch zuverlässig zu verhindern. Wo immer Dateinamen aus Nutzereingaben stammen, sollte zusätzlich eine strikte Extension-Allowlist und eine explizite Prüfung auf das Substring :// vorgeschaltet werden — unabhängig davon, welche Bibliothek die Datei letztlich verarbeitet.
Entscheidungsblock
- Sofort patchen: Composer-Update auf 1.30.5, Dependency-Baum auf transitive Nutzung prüfen.
- Kompensieren, falls Patch verzögert: Eingabevalidierung auf
://-Substring und Extension-Allowlist vorschalten. - Beobachten: Logs auf das Drei-Slash-Muster und ungewöhnliche Deserialisierungsfehler prüfen, auch nach dem Patch — als Nachweis, ob vor dem Update bereits Ausnutzungsversuche stattfanden.
Häufige Fragen zu CVE-2026-45034
Betrifft das auch Laravel- oder Symfony-Projekte, die über Wrapper-Pakete auf PhpSpreadsheet zugreifen?+
Ja, sofern das jeweilige Wrapper-Paket intern eine verwundbare PhpSpreadsheet-Version einbindet. Die Prüfung sollte sich daher nicht auf direkte composer.json-Einträge beschränken, sondern das aufgelöste composer.lock einschließen.
Gibt es bereits Angriffe in freier Wildbahn?+
Nach aktuellem öffentlichem Kenntnisstand ist keine bestätigte aktive Ausnutzung dokumentiert. Da die technischen Details und Proof-of-Concept-Code jedoch öffentlich zugänglich sind, sollte das nicht als Entwarnung verstanden werden.
Warum ist PHP 8.x weniger stark betroffen als PHP 7.x?+
PHP 8.x hat die automatische Objekt-Deserialisierung aus Phar-Metadaten in mehreren Punkten eingeschränkt, sodass der Bypass laut aktueller öffentlicher Analyse dort in eine Datei-Lese-Primitive statt in direkte Code-Ausführung mündet. Das ist weiterhin ernst zu nehmen, aber kein automatischer RCE-Pfad wie unter PHP 7.x.
Ist meine Anwendung betroffen, wenn ich PhpSpreadsheet nicht direkt einsetze?+
Möglich — viele Reporting-, Export- und Datenmigrations-Pakete für PHP-Frameworks binden PhpSpreadsheet transitiv ein. Prüfen Sie mit composer why phpoffice/phpspreadsheet, ob und über welches Paket eine Abhängigkeit besteht.
Reicht ein Composer-Update allein aus?+
Für die konkrete Lücke ja — Version 1.30.5 schließt den beschriebenen Bypass. Da die Ursache aber grundsätzlich in der Verlässlichkeit von parse_url() für Sicherheitsentscheidungen liegt, lohnt sich zusätzlich eine eigene, von der Bibliothek unabhängige Validierung nutzerkontrollierter Dateinamen.
Fazit
CVE-2026-45034 zeigt exemplarisch, wie brüchig Sicherheitsvalidierung sein kann, wenn sie sich auf das Randverhalten einer einzelnen Funktion wie parse_url() verlässt, ohne die tatsächliche Interpretation durch die dahinterliegende Stream-Schicht gegenzuprüfen. Der ursprüngliche Fix für CVE-2026-34084 war gut gemeint, deckte aber einen Randfall nicht ab — mit dem Ergebnis, dass der Schutz sich mit einem einzigen zusätzlichen Slash im Dateinamen vollständig aushängeln lässt. Für Betreiber bedeutet das: Composer-Updates sind notwendig, aber bei dateiverarbeitenden Bibliotheken reicht das allein oft nicht — eine eigene, unabhängige Validierungsschicht für nutzerkontrollierte Dateinamen bleibt sinnvoll, gerade weil sich zeigt, dass auch etablierte, viel genutzte Bibliotheken solche Bypasses übersehen können.
Quellen
Ich prüfe Ihren Composer-Dependency-Baum auf verwundbare PhpSpreadsheet-Versionen, härte Ihre Datei-Upload-Pfade und richte eine unabhängige Eingabevalidierung ein.
Dependency-Audit auf transitive PhpSpreadsheet-Nutzung, Review aller Codepfade mit nutzerkontrollierten Dateinamen, Einrichtung einer Extension-Allowlist und PHP-Härtung — damit ein einzelner übersehener Bypass nicht zum Sicherheitsvorfall wird.
Plattform-Betrieb statt Beratung auf Papier: Ich prüfe, härte und überwache Ihre PHP-Infrastruktur laufend.
Über den Autor

Kai Ole Hartwig
Programmiert seit 2002 – autodidaktisch gelernt, 2012 mit KO-Web selbständig gemacht. Über 100 Projekte, Fokus auf Security, Performance, Automatisierung und Qualität. Heute freiberuflich: DevSecOps-Beratung, Schulungen und Softwareentwicklung.