Contao-Camp 2024
Ergebnis 1 bis 9 von 9

Thema: Erweiterung umstellen von 4.4.x auf 4.8.x / Problem mit CSRF

  1. #1
    Contao-Nutzer
    Registriert seit
    10.09.2009.
    Beiträge
    27

    Standard Erweiterung umstellen von 4.4.x auf 4.8.x / Problem mit CSRF

    Hallo,

    kann es sein, dass sich die Unterstützung des Inserttag {{REQUEST_TOKEN}} zwischen 4.4 und 4.8 verändert hat?

    Folgendes Problem:
    Ich habe hier ein einezwei Erweiterungen, die bisher unter Contao 4.4 eingesetzt wurden und nun unter 4.8 laufen sollen. Beide Erweiterungen haben eines gemeinsam - sie haben im Template (mod_ouisearch) ein Formular eingebaut habe. Das Modul verbietet dann die Eingabe und spuckt entsprechend ein Ergebnis aus. Um das ganze sicher zu gestalten, sollte natürlich der REQUEST_TOKEN entsprechend übergeben werden (Hinweis: aktuell wird er allerdings von mir noch nicht geprüft).

    Das Problem ist nun folgendes. Rufe ich die Seite das erste mal überhaupt auf (also während noch keine Cookies etc. gesetzt wurden) wird kein REQUEST_TOKEN hinterlegt. Das Formular-Feld bleibt leer. Entsprechend ist auch der Cookie "csrf_https-contao_csrf_token" nicht im Browser gesetzt. Erst wenn ich z.B. auf der Seite z.B. das normale Kontaktformular aufrufe wird der Cookie gesetzt und im Anschluss (solange der Cookie noch existiert) wird auch der REQUEST_TOKEN in meiner Erweiterung gesetzt. Lösche ich den Cookie - dann ist wieder aus.

    Das Template und Modul sieht aktuell wie folgt aus. Das Modul ist ziemlich leergeräumt aktuell um alle Fehlerquellen auszuschließen:

    HTML-Code:
    {...}
    <form action="<?php echo \Contao\Environment::get('requestUri') ?>" id="testForm" method="get" enctype="application/x-www-form-urlencoded">
        <div class="formbody">
            <input type="hidden" name="FORM_SUBMIT" value="testForm">
            <input type="hidden" name="REQUEST_TOKEN" value="{{REQUEST_TOKEN}}">
            {...}
        </div>
    </form>
    {...}
    PHP-Code:
    <?php
    namespace xyz\zyx\Module;

    use 
    BackendTemplate;
    use 
    Contao\Config;
    use 
    Contao\Controller;
    use 
    Contao\FrontendTemplate;
    use 
    Contao\Input;
    use 
    Contao\PageError404;
    use 
    Contao\Pagination;
    use 
    Module;


    class 
    OuiSearchModule extends Module {
        
    /** @var string Template-Variable */
        
    protected $strTemplate 'mod_ouisearch';

        
    /**
         * Displays a wildcard in the back end.
         *
         * @return string
         */
        
    public function generate():string {
            
    self::loadLanguageFile('tl_ouisearch');

            if (
    TL_MODE === 'BE') {
                
    $template = new BackendTemplate('be_wildcard');

                
    $template->{'wildcard'} = "*** DUMMY TEXT *** ";
                
    $template->{'title'} = $this->headline;
                
    $template->{'id'} = $this->id;
                
    $template->{'link'} = $this->name;
                
    $template->{'href'} = 'contao/main.php?do=themes&amp;table=tl_module&amp;act=edit&amp;id=' $this->id;

                return 
    $template->parse();
            }

            return 
    parent::generate();
        }

        
    /**
         * Generates the module.
         */
        
    protected function compile():void {
            
    self::loadLanguageFile('tl_ouisearch');

            
    //Request-Token Init
            //$this->Template->{'REQUEST_TOKEN'} = "test:" . \RequestToken::get();
            //var_dump($this->Template->{'testtoken'});
        
    }
    }
    Das interessante dabei ist noch folgendes. Wie man am Programmcode sieht, hab ich einmal geschaut ob ich ein Request-Token selber ermitteln kann. Der Request-Token wird auch erzeugt und var_dump gibt ihn auch entsprechend aus. Sobald ich dann aber im Template mittels <?=$this->Template->{'testtoken'}?> einfügen möchte, bekommt das Template wiederum nur "test:" ... ohne Token, während var_dump wiederum "Test:"+Token ausgibt.

    Daher meine Frage - wo könnte der Fehler liegen? Ich weiß, dass \RequestToken mit Contao 5.x eingestampft wird. Allerdings mit 4.8 sollte das ganze doch eigentlich wie gehabt funktionieren, oder?

    Gruß,
    Jens

    Nachtrag:

    Nach etwas experimentieren ist mir noch etwas aufgefallen. Nehmen wir an der Nutzer ist noch nie auf der Seite gewesen und hat auch keine gesetzten Cookies. Nehmen wir jetzt folgende Klick-Pfade auf der Seite an:
    1.) Nutzer sucht nach der Seite über $suchmaschinen -> Nutzer klickt auf den Suchtreffer und kommt direkt auf die Seite mit der Erweiterung ... ==> Kein REQUEST_TOKEN wird gesetzt.
    2.) Nutzer kommt auf die Startseite (oder eine beliebige andere Unterseite) und klickt danach auf die Seite mit der Weiterung ... ==> REQUEST_TOKEN ist gesetzt

    Es scheint also, dass prinzipiell der REQUEST_TOKEN bzw. der der dazugehörige Cookie "csrf_https-contao_csrf_token" immer erst beim zweiten Aufruf der Seite gesetzt zu werden. Warum allerdings, ist mir aktuell ein Rätsel.
    Geändert von Jens (10.02.2020 um 18:40 Uhr)

  2. #2
    Contao-Fan
    Registriert seit
    20.10.2012.
    Ort
    Berlin
    Beiträge
    257

    Standard

    Das hat denke ich nichts mit Erweiterungen zu tun..
    Ich hab gerad das selbe Phänomen von einem Kunden zugetragen bekommen.
    Das war Version 4.8.5.
    Sobald man jungfräulich auf eine Seite mit Formular kommt (z.B. mit einem frischen incognito-Tab oder als Neukunde über Suchergebnisse) sind die request_token leer.
    Code:
    <input type="hidden" name="REQUEST_TOKEN" value="">
    und Formularversand scheitert mit entsprechender Fehlerseite.
    Aktualisiere (F5) ich die Seite vor dem Versand - sind sie vorhanden
    Code:
    <input type="hidden" name="REQUEST_TOKEN" value="xyz">
    Hab dann fix ein Update auf 4.8.8 gemacht aber es bleibt dabei.
    Soviel konnte ich feststellen:
    Cookie (csrf_https-contao_csrf_token) und
    Input (REQUEST_TOKEN) haben den selben Wert und sind beim ersten Seitenaufruf nicht gesetzt.
    Da ich nicht davon ausgehe, das jemand einen QuickFix ohne Update parat hat, steht wohl nächste Woche ein Update auf 4.9 an.
    Da konnte ich sowas noch nicht bemerken und die 4.4er Installationen, die ich gecheckt hab machen das auch nicht.

  3. #3
    Contao-Nutzer
    Registriert seit
    10.09.2009.
    Beiträge
    27

    Standard

    Hallo,

    sorry, dass ich hier nicht mehr weitergepustet hatte, was meine neusten Erkenntnisse dazu angeht (ging etwas unter, da ich gerade an einem Kundenprojekt arbeite).

    Aber zurück zu dem was du geschrieben hast:

    Genau so lässt sich das Problem regelmäßig auch bei einer "nackten" Installation feststellen und es betrifft tatsächlich praktisch alle Stellen, an denen eigentlich direkt der CSRF-Schutz greifen sollte. Was ich mangels Zeit nicht geprüft hatte war, ab welcher Version das ganze aufgetreten ist. Ich vermute, dass es bereits mit 4.8.0 gekommen ist, da laut Changelog in Zusammenhang mit dem speichern des Token geändert hat. Aber wie gesagt, ist nur eine Vermutung.

    Was ich sagen kann ist, dass dir ein Update auf 4.9.0 oder 4.9.1 nichts bringen wird, denn auch hier tritt der Fehler auf. Beim ersten Aufruf eines Formulars fehlt auch hier der CSRF-Token und der Nutzer wird (im Fall eines Contao Formulars) gezwungen eine eventuell vorhandene Sicherheitsfrage zu beantworten. Damit ist dann zwar im zweiten Aufruf der Token vorhanden, aber für den Nutzer ist das ganze ziemlich unschön und verwirrend.

    Wenn dich das ganze stört oder du ein eine Erweiterung einsetzt, die (wie bei meinem) den REQUEST_TOKEN verwendet/benötigt, dann bleibt dir vorerst nur auf 4.4 zu bleiben und auf die neuen Funktionen von 4.9 zu verzichten.

    Die Frage die sich mir aktuell stellt ist einfach, ob das ein "erwünschtes Verhalten" aktuell ist oder nicht. Allerdings stellt sich mir auch die Frage im Zusammenhang mit AJAX-Abfragen, in wieweit man diese zukünftig zuverlässig mit dem REQUEST_TOKEN schützen kann. Ich kann ja schlecht die REQUEST_TOKEN-Prüfung so verändern, dass ein leerer Token zugelassen wird. Es ist aber ebenso unschön, wenn jemand direkt via Suchmaschine auf eine Seite kommt, die ein Formular beinhaltet welches ein AJAX-Request auslösen sollte und diese dann fehlschlägt da der Token fehlt.

    Aktuell stehe ich was das angeht daher etwas in der Luft und lebe quasi mit der Sicherheitsabfrage bei Contao-Formulare (unter den oben genannten Vorraussetzungen) und dem erlauben eines leeren REQUEST_TOKEN. Wobei das durchaus zu Bauchgrummeln meinerseits führt (insbesondere bei der AJAX-Geschichte).

    Gruß,
    Jens

  4. #4
    Contao-Fan
    Registriert seit
    20.10.2012.
    Ort
    Berlin
    Beiträge
    257

    Standard

    Also ich mach wegen der Geschichte definitiv kein Downgrade... "erwünschtes Verhalten" kann das ja nicht sein.
    Hab die Tokenprüfung vorübergehend deaktiviert.
    Ich denk es wird mit diesem Ticket zu tun haben: https://github.com/contao/contao/issues/1491
    Ich hab zwar gar keine Cachzeiten im SiteRoot festgelegt - konnte aber folgendes bewirken:
    Einige Form-Module hatte ich im Layout über Insert-Tag eingebunden.
    Mit dem |uncached}} flag bekommen diese Formulare auch bei initialem Seitenaufruf ein Token.
    Dummerweise geht das nicht für Content-Elemente...

  5. #5
    Contao-Nutzer
    Registriert seit
    10.09.2009.
    Beiträge
    27

    Standard

    Zitat Zitat von andre.saage Beitrag anzeigen
    Also ich mach wegen der Geschichte definitiv kein Downgrade... "erwünschtes Verhalten" kann das ja nicht sein.
    Hab die Tokenprüfung vorübergehend deaktiviert.
    Ich denk es wird mit diesem Ticket zu tun haben: https://github.com/contao/contao/issues/1491
    Ich hab zwar gar keine Cachzeiten im SiteRoot festgelegt - konnte aber folgendes bewirken:
    Einige Form-Module hatte ich im Layout über Insert-Tag eingebunden.
    Mit dem |uncached}} flag bekommen diese Formulare auch bei initialem Seitenaufruf ein Token.
    Dummerweise geht das nicht für Content-Elemente...
    interessant - bei dem betroffenen Projekt ist für das SiteRoot tatsächlich eine Cachezeit hinterlegt. Ich hab daher einmal folgendes getestet:

    Cache für den SiteRoot deaktiviert:
    1. Contao Formular zeigt immer den REQUEST-TOKEN an.
    2. eigenes Modul "normal" als Inhaltselement eingefügt -> Erweiterung mit {{REQUEST_TOKEN}} im Template zeigt KEIN Token an
    3. eigenes Modul "normal" als {{insert-module::*|uncached}} eingefügt -> Erweiterung mit {{REQUEST_TOKEN}} im Template zeigt den Token an

    Cache für den SiteRoot aktiviert:
    1. Contao Formular zeigt immer den REQUEST-TOKEN an (seit 4.9.1? ich meine, vorher war beim ersten Versuch der Token leer)
    2. eigenes Modul "normal" als Inhaltselement eingefügt -> Erweiterung mit {{REQUEST_TOKEN}} im Template zeigt KEIN Token an
    3. eigenes Modul "normal" als {{insert-module::*|uncached}} eingefügt -> Erweiterung mit {{REQUEST_TOKEN}} im Template zeigt den Token an

    Es scheint also zumindest bei 4.9.1 sich etwas mit den Contao-Formulare etwas getan zu haben und es sieht so aus, als würde nur noch das Problem auf die Integration von Inhaltsmodule zu beschränken. Zumindest wäre die Integration über den insert-module-Umweg ein - wenn auch unschöner - Workaround für Contao Erweiterungen.

    Das mit den Formularen wäre nett, wenn das jemand kurz prüfen könnte ob bei euch auch mittlerweile bei Formulare der Request-Token beim Erstaufruf gesetzt wird. Was mir dabei auffällt ist übrigens, dass er Cache-Status für die Formular-Seite jetzt auf "Contao-Cache: miss" steht, während für alle anderen Seiten "Contao-Cache: fresh" angezeigt wird. Das würde dazu passen, dass anscheinend hier etwas korrigiert wurde.

    Gruß,
    Jens

  6. #6
    Contao-Nutzer
    Registriert seit
    10.09.2009.
    Beiträge
    27

    Standard

    ... noch ein kleiner Nachtrag für alle, die auf {{insert_module:*|uncached}} als Alternative setzen:
    Das ganze funktioniert im Prinzip ganz gut, hat aber eine Einschränkung. Javascripts, die per $GLOBALS['TL_JQUERY'] durch das Contao Modul hinzugefügt werden sollten, in diesem Fall einfach ignoriert.

  7. #7
    Contao-Nutzer
    Registriert seit
    10.09.2009.
    Beiträge
    27

    Standard

    Hallo,

    das Github Issue wird langsam durchaus interessant. Insbesondere die Aussage unter https://github.com/contao/contao/iss...ment-596981511 von aschempp.

    Verstehe ich es richtig, dass der CSRF-Token tatsächlich nicht mehr für Gäste erzeugt wird? Das würde bedeuten, dass man z.b. AJAX-Requests in seinen eigenen Erweiterungen nicht mehr über diesen Weg danach prüfen kann, ob der Request von der eigenen Seite kommt.

    Gruß,
    Jens

  8. #8
    Contao-Fan
    Registriert seit
    20.10.2012.
    Ort
    Berlin
    Beiträge
    257

    Standard

    Ich glaub ich versteh die Definition von "Gast" nicht.
    Ich bekomme immer eine PHPSESSID.
    Liegt das daran, dass der Cache bei mir gar nicht aktiviert ist?
    Den REQUEST_TOKEN und den csrf_https-contao_csrf_token bekomm ich hingegen immer erst nach Reload bzw. beim 2ten Seitenaufruf.

  9. #9
    Contao-Nutzer
    Registriert seit
    10.09.2009.
    Beiträge
    27

    Standard

    Zitat Zitat von andre.saage Beitrag anzeigen
    Ich glaub ich versteh die Definition von "Gast" nicht.
    Ich bekomme immer eine PHPSESSID.
    Liegt das daran, dass der Cache bei mir gar nicht aktiviert ist?
    Den REQUEST_TOKEN und den csrf_https-contao_csrf_token bekomm ich hingegen immer erst nach Reload bzw. beim 2ten Seitenaufruf.
    Mit Gast dürfte jeder Nutzer gemeint sein, die nicht über Symfony angemeldet sind. Aber ehrlich gesagt, verstehe ich es auch nicht wirklich und es wäre nett, wenn vielleicht jemand der sich mit dem Thema eher beschafft hat eventuell aufklären könnte.

    Was ich z.B: nicht verstehe im Zusammenhang z.B. mit eigenen Erweiterung. Nutze ich die eigene Erweiterung als Inhaltselement, wird beim ersten Aufruf kein Request-Token erzeugt. Wird das Modul dagegen als {{insert-module::*|uncached}} eingefügt, wird immer ein Request-Token erzeugt. Das würde der der Gast-Geschichte eigentlich widersprechen.

    Generell wäre dann auch einmal interessant, wie ihr in Contao 4.9 ein AJAX-Request in Zukunft einbauen würdet, der gegen "Fremdverwendung" abgesichert ist. Mir schwirren zwar schon einige Ideen im Kopf herum, aber vielleicht hat jemand eine relativ Lösung auf die ich noch nicht gekommen bin.

    Gruß,
    Jens

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)

Lesezeichen

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •