Julius: verhindern, dass Frickl script-Elemente in einem Attribut ausliest

Moin!

Aufgrund von Marcs Beitrag und dem dort verlinkten Vortrag habe ich mich mit dem neuen srcdoc-Attribut beschäftigt und festgestellt, dass die betreffende, kurze Erklärung im Wiki falsch und die Referenz zumindest missverständlich waren. Das habe ich – hoffentlich auch korrekt – verbessert.

Allerdings liest Frickl dummerweise script-Elemente aus, auch wenn sie sich – wie im Beispiel – in einem Attributwert befinden:

<p>Im folgenden iframe wird kein JavaScript ausgeführt:</p>
<iframe srcdoc="JavaScript? <script>alert('Hallöle!');</script><noscript>...kein JavaScript...</noscript>" sandbox></iframe>

Gibt es dafür eine Lösung (script-Elemente nicht parsen, falls sie sich innerhalb eines Attribut-Werts befinden?). Ich habe vorerst < und sicherheitshalber auch > escaped, aber eine allgemeine Lösung wäre natürlich – sofern realisierbar – vorzuziehen:

<iframe srcdoc="JavaScript? &lt;script&gt;alert('Hallöle!');&lt;/script&gt;&lt;noscript&gt;...kein JavaScript...&lt;/noscript&gt;" sandbox></iframe>

Nachtrag / BTW:
Ich konnte keine Primär-Quelle zu der Aussage finden, dass das srcdoc-Attribut zusammen mit dem Einsatz des sandbox-Attribut gedacht und dass alle Browser, die srcdoc implementieren, sandbox ebenfalls beherrschen müssen (dass dem augenscheinlich so ist, kann man auf caniuse sehen...). Worauf ich hinaus will: Es könnte eines Tages ein Browserhersteller auf die Idee kommen, zuerst srcdoc und dann erst sandbox zu implementieren, falls das nicht in der Spec stünde – auf die Isolation von unsicheren Inhalten wäre damit kein Verlass mehr!

Gruß
Julius

  1. Lieber Julius,

    Allerdings liest Frickl dummerweise script-Elemente aus, auch wenn sie sich – wie im Beispiel – in einem Attributwert befinden:

    das liegt daran, dass das dahinterliegende PHP-Script mit einem relativ simplen preg_match_all operiert, anstatt einen kompletten HTML-Parser zu bemühen:

    // JavaScript: <script>
    if (preg_match_all(
      '~(?is)<script[^>]*>(.*?)</script>~',
      $text,
      $test
    )) {
      foreach ($test[1] as $js) {
        $data['javascript'] .= $js;
      }
    }
    

    Gibt es dafür eine Lösung (script-Elemente nicht parsen, falls sie sich innerhalb eines Attribut-Werts befinden?).

    Prinzipiell schon: Einen HTML-Parser bemühen.

    Ich habe vorerst < und sicherheitshalber auch > escaped,

    Sehr gut. Das ist momentan die sicherste Lösung.

    aber eine allgemeine Lösung wäre natürlich – sofern realisierbar – vorzuziehen:

    Welchen Parser empfiehlst Du, dass ich ihn in einer Extension für eine veraltete MediaWiki-Version einsetze? Aktuell habe ich etwas Erfahrung mit masterminds/html5, was mir aber gehörig überdimensioniert erscheint. Geht es nicht etwas einfacher?

    Liebe Grüße,

    Felix Riesterer.

    1. Hallo Felix Riesterer,

      Welchen Parser empfiehlst Du, dass ich ihn in einer Extension für eine veraltete MediaWiki-Version einsetze?

      Ich gehe davon aus, dass noch in diesem Monat geupdatet wird.

      Bis demnächst
      Matthias

      --
      Rosen sind rot.
      1. Lieber Matthias,

        wird auf die neuestmögliche Version geupdatet? Und wenn ja, wie steht es da mit der Kompatibilität unserer Extension?

        Liebe Grüße,

        Felix Riesterer.

        1. Hallo Felix Riesterer,

          wird auf die neuestmögliche Version geupdatet?

          Ja.

          Bis demnächst
          Matthias

          --
          Rosen sind rot.
          1. Tach!

            wird auf die neuestmögliche Version geupdatet?

            Ja.

            ... Komma wenn man das "möglich" auf LTS-Versionen einschränkt.

            dedlfix.

    2. Hallo Felix,

      Allerdings liest Frickl dummerweise script-Elemente aus, auch wenn sie sich – wie im Beispiel – in einem Attributwert befinden:

      das liegt daran, dass das dahinterliegende PHP-Script mit einem relativ simplen preg_match_all operiert, anstatt einen kompletten HTML-Parser zu bemühen:

      Dachte mir schon, dass das was damit zu tun haben könnte.

      Ich habe vorerst < und sicherheitshalber auch > escaped,

      Sehr gut. Das ist momentan die sicherste Lösung.

      Aber leider nicht sehr elegant. Ich stelle mir dann das Szenario vor, dass jemand den Beispiel-Quelltext im Wiki-Artikel verändert und dann einfach in das Live-Beispiel Copy-Pastet und dann das Escapen übersieht, woraufhin es knallt. Natürlich könnte man auch im Artikel selbst die betreffende Stelle escapen, aber das wäre der Übersicht nicht zuträglich und (erst seit HTML5?) muss ja bis auf das Anführungszeichen nichts mehr im Attribut escaped werden.

      aber eine allgemeine Lösung wäre natürlich – sofern realisierbar – vorzuziehen:

      Welchen Parser empfiehlst Du, dass ich ihn in einer Extension für eine veraltete MediaWiki-Version einsetze? Aktuell habe ich etwas Erfahrung mit masterminds/html5, was mir aber gehörig überdimensioniert erscheint. Geht es nicht etwas einfacher?

      Ich habe mal mit SimpleXML einen einfachen Feedreader gebastelt, damit kann man über Umwege wohl auch HTML einlesen. Was hat der HTML-Parser mit der MediaWiki-Version zu tun?

      Warum wählt man für die Beispiele nicht (optional) ein Format, wie es auch bei CodePen praktiziert wird? Die scheinen HTML, CSS und JS ja auch separat zu speichern. – Gut, man kann vermutlich ohne JS nichts in den Head-Bereich der Seite schreiben, aber sonst?

      Gruß
      Julius

      1. Lieber Julius,

        Dachte mir schon, dass das was damit zu tun haben könnte.

        :-)

        Ich stelle mir dann das Szenario vor, dass jemand den Beispiel-Quelltext im Wiki-Artikel verändert und dann einfach in das Live-Beispiel Copy-Pastet und dann das Escapen übersieht, woraufhin es knallt.

        Wo genau soll es da knallen? Die Code-Beispiele dürfen meines Wissens nicht von allen Benutzern editiert werden.

        Natürlich könnte man auch im Artikel selbst die betreffende Stelle escapen, aber das wäre der Übersicht nicht zuträglich und (erst seit HTML5?) muss ja bis auf das Anführungszeichen nichts mehr im Attribut escaped werden.

        Die Beispiele sind sozusagen statische HTML-Dokumente, die über die Extension geladen und gespeichert werden können. Wenn man das im Frickl anschauen möchte, dann wird dieses HTML-Dokument von meinem PHP-Script in der gezeigten notdürftigen Art "geparst".

        Ich habe mal mit SimpleXML einen einfachen Feedreader gebastelt, damit kann man über Umwege wohl auch HTML einlesen.

        Da könnte eventuell auch die DOMDocument-Klasse von PHP genügen, sofern wir mit der zugrunde liegenden libxml keinen Schiffbruch erleiden. Das müsste man™ mal testen.

        Was hat der HTML-Parser mit der MediaWiki-Version zu tun?

        Diese ist an sich schon ein Schwergewicht. Da wäre mir für die Extension ganz lieb, wenn man dafür nicht noch weitere Schwergewichte auffahren müsste. Außerdem wäre es chic, wenn man auf eine in der MediaWiki-Software möglicherweise schon vorhandene Parserklasse zurückgreifen könnte. Aber da ich momentan wirklich kaum Zeit finde (mein Posting-Volumen hält sich z.Zt. sichtbar in engen Grenzen), mag ich mich dahingehend jetzt noch nicht schlau machen.

        Warum wählt man für die Beispiele nicht (optional) ein Format, wie es auch bei CodePen praktiziert wird? Die scheinen HTML, CSS und JS ja auch separat zu speichern. – Gut, man kann vermutlich ohne JS nichts in den Head-Bereich der Seite schreiben, aber sonst?

        Wie machst Du dann die Sache mit den Code-Beispielen, wenn Du ein "statisches" HTML-Dokument haben möchtest? Immerhin geht es in der Doku auch um die vollständige HTML-Struktur (inklusive Doctype), die ich in dieser Weise gerade noch nicht als speicherbar sehe...

        Liebe Grüße,

        Felix Riesterer.

        1. Hallo Felix,

          Ich stelle mir dann das Szenario vor, dass jemand den Beispiel-Quelltext im Wiki-Artikel verändert und dann einfach in das Live-Beispiel Copy-Pastet und dann das Escapen übersieht, woraufhin es knallt.

          Wo genau soll es da knallen?

          Im Beispiel im Wiki-Artikel ist aus Gründen der Übersichtlichkeit das script-Element im Attributwert nicht escaped, im Live-Beispiel dagegen schon. Wenn jetzt Änderungen am Beispiel im Artikel vorgenommen werden, müssen diese ins Live-Beispiel übertragen werden. Es kann da durchaus sein, dass dabei das Escapen von <script> im Attribut vergessen wird. Dann parst Frickl das JavaScript im srcdoc-Attribut im iframe und der Browser führt das JavaScript infolgedessen aus, obwohl ja eigentlich demonstriert werden sollte, dass sandbox gerade das verhindert. Das meinte ich mit „knallen“. Ist zugegebenermaßen auch ein ziemlicher Spazialfall, im Allgemeinen funktioniert Frickl ja :-)

          Ich sehe aber gerade, dass auch der Syntax-Highlighter von MediaWiki da aussteigt und den Attributwert „für beendet erklärt“ (obwohl das Beispiel valide ist):
          Syntax-Highlighting im SELFHTML-Wiki

          Vielleicht escape ich das dann doch lieber auch im Artikel...

          Was hat der HTML-Parser mit der MediaWiki-Version zu tun?

          Diese ist an sich schon ein Schwergewicht. Da wäre mir für die Extension ganz lieb, wenn man dafür nicht noch weitere Schwergewichte auffahren müsste. Außerdem wäre es chic, wenn man auf eine in der MediaWiki-Software möglicherweise schon vorhandene Parserklasse zurückgreifen könnte.

          Ah, verstehe. Cacht du die Ergebnisse eigentlich (damit könnte man den Overhead abfangen)? So oft ändern sich die Beispiele ja auch nicht (alternativ oder besser könnte man ja auch Cache-Datum mit dem Änderungsdatum des Beispiels vergleichen).

          Aber da ich momentan wirklich kaum Zeit finde (mein Posting-Volumen hält sich z.Zt. sichtbar in engen Grenzen), mag ich mich dahingehend jetzt noch nicht schlau machen.

          Das mache ich dir garantiert nicht zum Vorwurf. Ich wollte das Problem nur mal erwähnen, vielleicht lässt sich ja irgendwann eine Lösung dafür (bzw. eine so allgemeine Lösung für Probleme, die wir bisher noch nicht kennen) einbauen. Ist das Meta-Forum der passende Ort für solche Diskussionen oder ist Frickl irgendwo auf GitHub zu finden? Im SELFHTML-GitHub-Account konnte ich nämlich nichts finden.

          Warum wählt man für die Beispiele nicht (optional) ein Format, wie es auch bei CodePen praktiziert wird? Die scheinen HTML, CSS und JS ja auch separat zu speichern. – Gut, man kann vermutlich ohne JS nichts in den Head-Bereich der Seite schreiben, aber sonst?

          Wie machst Du dann die Sache mit den Code-Beispielen, wenn Du ein "statisches" HTML-Dokument haben möchtest?

          Ich schreibe das separat gespeichert HTML, CSS und JS in ein HTML-Grundgerüst und gebe das aus bzw. reiche die Inhalte separat an Frickl durch, das die dann zusammenbaut. Theoretisch müsste das funktionieren – ich muss aber auch dazu sagen, dass ich nicht weiß (eine Idee habe ich jetzt vielleicht) wie Frickl genau funktioniert.

          Immerhin geht es in der Doku auch um die vollständige HTML-Struktur (inklusive Doctype), die ich in dieser Weise gerade noch nicht als speicherbar sehe...

          Frickl zeigt ja auch immer nur einen Ausschnitt aus dem HTML an, insofern wäre es elegant, auch nur den zu speichern. Dann könnte man so etwas speichern:

          <s-example>
            <s-title>Titel / Überschrift</s-title>
            <html>
              <button>Klick mich!</button>
            </html>
            <style-css>
              botton {color:green;}
            </style-css>
            <script-js>
              alert('Hallo!');
            </script-js>
          </s-example>
          

          Daraus baut man dann so etwas (oder die Form, wie Frickl es braucht):

          <!DOCTYPE html>
          <html lang="de">
          <head>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0;" />
            <link rel="stylesheet" media="screen" href="./Beispiel:SELFHTML-Beispiel-Grundlayout.css" />
            <title>Beispiel: Titel / Überschrift</title>
            <style>
              botton {color:green;}
            </style>
          </head>
          <body>
            <h1>Beispiel: Titel / Überschrift</h1>
            <main>
              <button>Klick mich!</button>
            </main>
          <script>
          alert('Hallo!');
          </script>
          </body>
          </html>
          

          Die Vorteile liegen in der leichten Anpassbarkeit des HTML-Grundgerüsts (es wird ja zentral gespeichert) und der Stabilität der Lösung (der Beispiel-Administrator bestimmt, was ein Script ist und was nicht). Außerdem könnte man dank der Kollisions-Freiheit weiterhin mit RegEx arbeiten. Ich bin nicht so der XML-Profi, aber eventuell könnte man mithilfe von Namespaces (man kann immer noch mit RegEx arbeiten) das umschließende XML so auszeichnen, dass es garantiert nicht mit dem enthaltenen HTML kollidiert (script-js kann ja als selbst definiertes Element durchaus auch in HTML existieren).

          Gruß
          Julius