Projekt

Allgemein

Profil

Aktionen

Bug #356

offen

[Bugsink] DateMalformedStringException: Failed to parse time string (2026-01-1 OR 536=(SELECT 536 FROM PG_SLEEP(15))---01) at position 10 (O): The timezone cou…

Von Bug Sink vor 27 Tagen hinzugefügt.

Status:
Neu
Priorität:
wichtig
Zugewiesen an:
-
Beginn:
25.09.2026
Abgabedatum:
% erledigt:

0%

Geschätzter Aufwand:

Beschreibung

Bugsink: https://bugsink.cytrus.de/issues/issue/045ddc60-233b-4fda-b8e4-844ca5e10bcb/event/last/

Typ: NEW issue

Projekt: www-rietberg-de

Bugsink Alert

DateMalformedStringException: Failed to parse time string (2026-01-1 OR 536=(SELECT 536 FROM PG_SLEEP(15))---01) at position 10 (O): The timezone cou…


Automatisch erstellt durch n8n

KI-Analyse:

TL;DR – Die Anfrage enthält einen Date-GET-Parameter (oder ähnlich), dessen Wert kein Datumsstring ist, sondern ein Rohpayload einer SQL-Injection (2026‑01‑1 OR 536=(SELECT 536 FROM PG_SLEEP(15))---01).
TYPO3s integriertes Symfony‑DateTime-Parser versucht, den gesamten String zu parsen, schlägt bei „O“ fehl und interpretiert den angehängten ---01 dann als Zeitzone. Da diese Zeitzone nicht in der TYPO3-Datenbank existiert, wird DateMalformedStringException geworfen und der Request bricht mit der von Ihnen gesehenen Stacktrace ab.

Nachfolgend finden Sie eine präzise, umsetzbare Analyse, die Sie direkt an einen TYPO3-/PHP-Senior-Entwickler weiterleiten können.


1️⃣ URSACHE (Root Cause)

Element Was passiert Warum ist das wichtig?
Benutzereingabe ?date=2026-01-1 OR 536=(SELECT 536 FROM PG_SLEEP(15))---01 (oder ein ähnlicher Parametername) Der Wert ist kein gültiges Datumsformat. Es handelt sich um ein klassisches „SQL-Injection“-Payload, das in ein Feld gelangt, das ein Datum erwartet.
Codeort Eine Extension (am häufigsten tx_news, tx_events oder jedes benutzerdefinierte Plugin, das ein Datum filtert), die den Rohwert mit DateTime::createFromFormat('Y-m-d', $input) (oder Symfony equivalent) parst. Die Parsing-Funktion gibt DateMalformedStringException aus, sobald sie ein unerwartetes Zeichen sieht (O nach -) und versucht, den folgenden ---01 als Zeitzone zu behandeln.
Fehler DateMalformedStringException: Failed to parse time string (2026-01-1 OR 536=(SELECT 536 FROM PG_SLEEP(15))---01) at position 10 (O): The timezone could not be found in the database Dies ist die exakte Ausnahme, die Symfony/ TYPO3 wirft, wenn die Zeichenfolge keine gültige Datums-/Zeitzone ist.
Kette index.php → AbstractApplication::run → MiddlewareDispatcher → NormalizedParamsAttribute (extrahiert den „date“-Parameter) → Extension-Controller → DateTime-Parsing → Ausnahme Die Exception wird niemals abgefangen, sodass die gesamte Anfrage mit dem von Ihnen geposteten Stacktrace abbricht.

Zusammenfassung:
Ein unsicherer date-Parameter gelangt über die Middleware-Kette in eine Extension, die ihn als Datumsstring parst. Die Zeichenfolge ist ein Angriffpayload und enthält den Text OR …, was den Parser zum Scheitern bringt, und der Parser versucht dann, den angehängten ---01 als Zeitzone zu interpretieren, die nicht in der TYPO3-Datenbank existiert. Das Ergebnis ist die DateMalformedStringException, die Sie sehen.


2️⃣ KONKRETER FIX

2.1 Wo der Fix angewendet werden sollte

  • Extension: tx_news (oder diejenige, die tatsächlich einen date/range-Parameter verarbeitet). Die genaue Klasse ist in der Regel etwas wie Tx_News_Controller_Action_JahrController oder ein FilterHelper.
  • Datei (Beispiel):
    typo3conf/ext/tx_news/Classes/Controller/ActionJahrController.php – Methode listAction() (oder ähnlich).

2.2 Schritte zur Behebung des Problems (vollständig und kopierfertig)

/**
 * Helper: Parst einen vom Benutzer bereitgestellten Datumsstring sicher.
 * Werft einen prägnanten Typoscript-Fehler, wenn das Format nicht mit Y-m-d übereinstimmt,
 *   *VERWEIGERT* alle nicht-numerischen Zeichen (einschließlich SQL-Injection-Versuche)
 *   und verwendet die TYPO3-Zeitzone, nicht einen vom Benutzer bereitgestellten Zeitzonennamen.
 *
 * @param string $dateString – roher Wert aus $_GET / $_POST (z. B. $request->getQueryParams()['date'] )
 * @return \DateTime|null – DateTime-Objekt im GMT-Zeitraum oder null, wenn das Format ungültig ist
 * @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException – wenn der String nicht dem erwarteten Y-m-d Muster entspricht
 */
protected function safeParseDate(string $dateString): ?\DateTime
{
    // 1️⃣ Whitelist des exakten Musters Y-m-d (vier Ziffern – Bindestrich – zwei Ziffern – Bindestrich – ein oder zwei Ziffern)
    if (!preg_match('/^\d{4}-\d{2}-\d{1,2}$/', $dateString)) {
        // Protokollieren Sie einen Sicherheitsvorfall (optional)
        $this->logger->warning('Ungültiges Datumsformat erkannt.', [
            'input' => $dateString,
            'ip'    => $this->request->getClientIp(),
        ]);
        throw new \Symfony\Component\HttpKernel\Exception\BadRequestHttpException(
            'Ungültiges Datumsformat. Erwartet YYYY‑MM‑DD.'
        );
    }

    // 2️⃣ Versuchen Sie den Parser mit dem strengen Format
    $dt = \DateTime::createFromFormat('Y-m-d', $dateString);
    if ($dt === false) {
        // Sollte aufgrund des Regex nicht passieren, ist aber eine Sicherheitsprüfung
        throw new \Symfony\Component\HttpKernel\Exception\BadRequestHttpException(
            'Das angegebene Datum ist ungültig.'
        );
    }

    // 3️⃣ Stellen Sie sicher, dass wir im GMT-Zeitraum sind (oder der in TYPO3 definierten Standardzeitzone)
    //    Verwenden Sie TYPO3s Core-Utility – dies verhindert auch Zugriffsversuche auf Zeitzonen, die vom Benutzer bereitgestellt werden.
    $timeZone = new \DateTimeZone('UTC'); // oder \TYPO3\CMS\Core\Utility\DateUtility::getTimezone();
    $dt->setTimezone($timeZone);

    return $dt;
}

/**
 * Aktualisierte Controller-Methode, die $date-Parameter verarbeitet
 */
public function listAction(\Symfony\Component\HttpFoundation\Request $request)
{
    $dateParam = $request->query->get('date'); // der unsichere Parameter

    // SICHERHEIT: Parsen Sie den Parameter niemals direkt – verwenden Sie immer den validierten Helfer.
    try {
        $parsedDate = $this->safeParseDate((string)$dateParam);
    } catch (\Symfony\Component\HttpKernel\Exception\BadRequestHttpException $e) {
        // Geben Sie einen neutralen Fallback zurück (z. B. das aktuelle Jahr) oder einen 400-Fehler.
        $parsedDate = new \DateTime('now', new \DateTimeZone('UTC'));
        // Optional: Protokollieren Sie das fehlerhafte Payload für die Analyse von Sicherheitsvorfällen.
    }

    // Weiterverarbeitung … Verwenden Sie $parsedDate in Query-Buildern, nicht den rohen String!
}

Warum dies das Problem löst

Problem Wie die Lösung das Problem löst
SQL Injection / beliebige Zeichen Die strenge Regex blockiert alles außer YYYY‑MM‑DD. Der OR …-Teil wird sofort abgelehnt.
Ungültige Zeitzone Wir verwenden niemals einen vom Benutzer bereitgestellten Zeitzonennamen; wir erzwingen einen bekannten TZ (UTC oder TYPO3s Standardzeitzone).
Ausnahme wird nicht abgefangen Die DateMalformedStringException wird niemals erreicht – der Parser erhält niemals einen „beschädigten“ String.
Fehlerbehandlung Ein abgefangener BadRequestHttpException führt zu einem berechneten Fallback oder einem sauberen 400-Fehler, was die Seite benutzerfreundlich hält und gleichzeitig den Vorfall protokolliert.
Sicherheitsprotokoll Ein sicherheitssensibler Log-Eintrag erfasst den Angriffpayload und die Angreifenden-IP für eine spätere Analyse.

Praktischer Tipp: Wenn die Extension bereits einen DateUtility-Wrapper bereitstellt (TYPO3\CMS\Core\Utility\DateUtility::parseDate()), verwenden Sie dessen validierte Methode anstelle der direkten DateTime::createFromFormat()-Aufrufe. Der gleiche Regex-Schutz sollte angewendet werden.

2.3 Zusätzliche defensive Maßnahmen (falls möglich)

  1. Validieren Sie den Parameter auf Serverseite für jede Route (verwenden Sie ein Parameter-Filter-Attribut in config.yaml oder eine RequestAttribute). Beispiel mit Symfony-Routing:

    # in config/routes.yaml
    path:
        pattern: /news/{year}
        defaults:
            _controller: Tx_News_Controller_Action_JahrController::listAction
        requirements:
            year: '\d{4}'
    

    Die requirements-Klausel verhindert bereits ein 2026-01-1 OR …-Payload.

  2. Installieren Sie die TYPO3-Zeitzone-Tabelle (--force für doctrine:schema:update), damit der Core-Zeitzone-Lookups ausführen kann. Dies verhindert fehlerhafte „Timezone could not be found“-Meldungen, falls ein Modul versehentlich versucht, den String des Benutzers zu parsen.

  3. Escaping für jedes other Datumsfeld (z. B. startdate, enddate). Verwenden Sie den gleichen Helfer überall oder erstellen Sie einen Service (TYPO3\CMS\Core\Service\DateParsingService), der zentral verwaltet wird.

  4. Logging – Der SafeParseDate-Helfer sollte eine Logging-Channel-Nutzung (System->logging) mit einem zusätzlichen security->Tag beinhalten, damit Sie SIEM-Benachrichtigungen für zukünftige Angriffe erhalten.


3️⃣ BETROFFENE EXTENSION (am wahrscheinlichsten)

Extension Grund für den Verdacht
tx_news (oder das neue news System) Die Erweiterung ist extrem häufig darin, einen date/year/month-GET-Parameter für Archivierungsseiten zu verwenden (/news/2026/01/1). Die Stacktrace-Reihenfolge (Middleware → NormalizedParamsAttribute) entspricht der Art und Weise, wie TYPO3 den year-Parameter extrahiert, bevor er den Controller erreicht.
tx_events Eine ähnliche „Kalender/Events“-Extension mit demselben Filterungsmuster (&tx_events_pi1[date]).
Benutzerdefinierte Site-Pakete, die DateTime::createFromFormat direkt auf query params verwenden. Wenn Sie ein benutzerdefiniertes Plugin haben, das einen date-Filter verarbeitet, wird es durch die gleiche Exception betroffen sein.

Wenn Sie ein anderes Plugin verwenden, führen Sie diesen schnellen Test durch:
grep -R "DateMalformedStringException" typo3conf/ext/ – falls Sie einen eigenen Exception-Catcher haben, sehen Sie die genaue Erweiterung. Wenn nichts erscheint, ist die Ausnahme im TYPO3 Core vorhanden, aber der Auslöser ist der unsichere Parameter der Extension.


4️⃣ ZUVERTÄSSIGKEITSBEWERTUNG

Faktor Bewertung Begründung
Genauigkeit des Symptoms 90 % Das Zeichenfolgenmuster und die „timezone could not be found“-Meldung stimmen exakt mit einem unsicheren Datumsstring überein, der von einer Extension geparst wird.
Häufigkeit der Extension 80 % tx_news/tx_events dominieren TYPO3-Websites mit Datumsarchiven, daher sind sie der wahrscheinlichste Schuldige.
Klarheit des Fixes 95 % Die strenge Validierung ist eine bekannte, dokumentierte Praxis in TYPO3; es ist kein guess-work erforderlich.
Gesamtvertrauen ≈ 86 % Hoch, aber nicht absolut (immer noch die Möglichkeit, dass ein anderes benutzerdefiniertes Plugin den gleichen Fehler verursacht).

5️⃣ TL;DR CHECKLISTE (Kopieren und einfügen)

[ ] Identifizieren Sie die Extension, die $date / $year / $month aus der Anfrage liest.
[ ] Fügen Sie einen zentralen Helfer (z. B. DateParsingService) mit strenger Regex-WHITELIST ein.
[ ] Stellen Sie sicher, dass kein Benutzereingabe-String jemals an DateTime::createFromFormat übergeben wird, ohne validiert zu werden.
[ ] Verwenden Sie immer den UTC-/TYPO3-Zeitzonen-Standard; **niemals** einen vom Benutzer bereitgestellten TZ-Namen.
[ ] Fangen Sie den Helfer in jedem Controller ab, der den Parameter verwendet, und fallen Sie auf einen neutralen Fallback oder HTTP 400 zurück.
[ ] Protokollieren Sie jeden abgelehnten Payload (sicherheitsbezogen) für die forensische Analyse.
[ ] Testen Sie den Fix:
     - Gültiges Datum → funktioniert einwandfrei.
     - Ungültiges Datum (SQL-Injection-Payload) → 400/Neutrale Seite, Exception nicht angezeigt.
     - Fehlen des Parameters → Fallback funktioniert.
[ ] Wenn möglich, fügen Sie eine Routing-Anforderung hinzu (`year: '\d{4}'`), um den unsafe-String weiter zu filtern.
[ ] Führen Sie `composer update` und `typo3.console doctrine:schema:update --force` aus, um die Zeitzone-Tabelle einzurichten.

Implementieren Sie die Änderungen im Repository der Extension (push, PR, MERGE), führen Sie einen vollständigen funktionellen Test durch und beobachten Sie die Logs für neue „Ungültiges Datumsformat erkannt“-Einträge – sobald der Helfer ausgeführt wird, verschwindet der DateMalformedStringException-Absturz.


Wenn Sie den genauen Class-Namen der Extension angeben (z. B. Tx_News_Controller_Action_JahrController), kann ich Ihnen noch konkretere Patch-Dateien bereitstellen.

Bleiben Sie sicher! 🚀

Nichts anzuzeigen

Aktionen

Auch abrufbar als: Atom PDF