it-swarm-eu.dev

Wie verwende ich Markdown sicher?

Wie verwende ich die Markdown-Bibliothek sicher? Was muss ich tun, um sicherzustellen, dass die Ausgabe sicher in meine Webseite aufgenommen werden kann?

Ich möchte nicht vertrauenswürdigen Benutzern erlauben, Inhalte einzugeben (im Markdown-Format). Ich werde den Markdown-Prozessor verwenden, um HTML zu generieren, und ich möchte diesen HTML-Code in meine Webseite aufnehmen. Was muss ich tun, um sicherzustellen, dass dies sicher ist und keine selbstverschuldete XSS-Sicherheitsanfälligkeit vorliegt? Welche Argumente muss ich übergeben? Gibt es eine Vor- oder Nachbearbeitung, die ich durchführen muss? Ich benutze die Python-Markdown-Bibliothek, wenn das relevant ist.

45
D.W.

Empfohlene Verwendung. Die kurze Antwort lautet: Verwenden Sie markdown(untrusted, safe_mode=remove, enable_attributes=False).

Stellen Sie sicher, dass Sie über eine aktuelle Version der Markdown-Bibliothek verfügen, da ältere Versionen einige Sicherheitsprobleme aufweisen.

Sie können die Ausgabe auch über ein HTML-Desinfektionsprogramm wie HTML Purifier ausführen.

Begründung. Es ist eine gute Idee, enable_attributes Zu deaktivieren. Während die neuesten Entwicklungsversionen der Python Markdown-Bibliothek enable_attributes Standardmäßig deaktivieren, wenn Sie safe_mode) Deaktivieren , haben frühere Versionen dies nicht getan Folglich ist das Setzen von safe_modein den meisten Versionen der Markdown-Bibliothek nicht ausreichend . Wenn Sie nur safe_mode setzen, ist das Ergebnis unsicher:

import markdown
>>> markdown.markdown("{@onclick=alert('hi')}some paragraph", safe_mode=True)
u'<p onclick="alert(\'hi\')">some paragraph</p>'

Im Moment sind die Fixes nur in Git vorhanden. Zum Zeitpunkt dieses Schreibens bleibt die neueste veröffentlichte Version von Python Markdown (2.1.1)) anfällig, es sei denn, Sie setzen explizit enable_attributes=False. Daher ist es plausibel, dass derzeit viele Systeme vorhanden sind using Python Markdown ist möglicherweise anfällig.

Die Dokumentation könnte Benutzer von Markdown besser vor diesen Fallstricken warnen. Es werden Dinge wie "Möglicherweise möchten Sie auch enable_attributes=False Festlegen, wenn Sie safe_mode Verwenden" angegeben, ohne dass angegeben wird, dass bei Nichtbeachtung ein XSS-Loch mit allen Versionen außer der neuesten Version der Bibliothek erstellt wird. In späteren Versionen der Dokumentation heißt es, dass die Einstellung enable_attributes "Möglicherweise einem nicht vertrauenswürdigen Benutzer ermöglichen kann, JavaScript in Ihre Dokumente einzufügen". Es ist klarer zu sagen, dass die Einstellung enable_attributes es Benutzern ermöglicht, Javascript in Ihre Dokumente einzufügen, und daher sehr unsicher ist, ob der Markdown von einer nicht vertrauenswürdigen Quelle stammt.

Zweifel. Trotzdem bin ich nicht 100% sicher, ob das Ergebnis sicher ist, selbst wenn es wie oben empfohlen verwendet wird. Die Entwickler haben folgende Kommentare abgegeben:

"abgesicherter Modus" war eine schlechte Namenswahl, die wir weiterhin für die Abwärtsvergleichbarkeit verwenden (alter Code funktioniert immer noch mit unseren neueren Versionen). Was es wirklich ist, ist ein No-Markup-Modus. Mit anderen Worten, es ist nur eine Möglichkeit, rohes HTML zu verbieten und garantiert wirklich keine Sicherheit.

Diese Art von Kommentaren ist ein bisschen beängstigend.

In früheren Versionen der Python Markdown-Bibliothek) erscheint mir die HTML-Bereinigung etwas fragil, daher bin ich mir nicht sicher, ob ich früheren Versionen der Markdown-Bibliothek vertrauen würde, unabhängig davon, welche Flags bestanden werden. Beachten Sie Folgendes:

>>> markdown.markdown("[Example](javascript://alert%28%22xss%22%29)", safe_mode=True)
u'<p><a href="javascript://alert%28%22xss%22%29">Example</a></p>'

Das Zulassen von URLs im javascript: - Stil durch Markdowns Verarbeitung scheint mir eine ziemlich zweifelhafte Designentscheidung zu sein. Es fühlt sich so an, als wäre dies nur einen Katzensprung von XSS entfernt. Alles, was fehlt, ist eine Möglichkeit, aus dem Kommentar im C++ - Stil (//) Auszubrechen, und das Spiel ist vorbei. Zum Beispiel:

>>> markdown.markdown("[Example](javascript://\nalert%28%22xss%22%29)", safe_mode=True)
u'<p><a href="javascript://&#10;alert%28%22xss%22%29">Example</a></p>'

Wie sicher sollte ich sein, dass kein Browser dieses Javascript ausführt? Ich weiß nicht, aber es gibt mir keine warmen, verschwommenen Gefühle. Wenn es sicher ist, ist es nur blindes Glück.

Glücklicherweise scheint die neueste veröffentlichte Version von Markdown eine strengere Filterung des Skripts durchzuführen, wenn Sie enable_attributes=False Festlegen. Stellen Sie jedoch sicher, dass Sie enable_attributes=False Festlegen. Andernfalls greift Markdown auf die fragile HTML-Bereinigung zurück, die in früheren Versionen gefunden wurde, und ich bin nicht sicher, ob dieses Schema sicher ist.

Was nicht zu tun ist. Folgendes ist nicht sicher: markdown(escape(untrusted)).

  • Sie könnten denken, dass das erste Entkommen der Eingabe den gesamten HTML-Code entfernen und diese Verwendung sicher machen würde. Tatsächlich habe ich gesehen, dass dies in einigen Systemen verwendet und von einigen empfohlen wird. Es ist jedoch tatsächlich unsicher, da das Escapezeichen nicht ausreicht, um URLs sicher zu machen. Zum Beispiel kann diese Verwendung von Markdown durch "[clickme](javascript:alert%28%22xss%22%29)" besiegt werden. Im Allgemeinen ist das Entkommen der Eingabe für Markdown nicht der richtige Ansatz ; Der richtige Ansatz besteht darin, Markdown auf die entsprechende Weise aufzurufen (und möglicherweise auch einen HTML-Filter auf die Ausgabe anzuwenden, wenn Sie zusätzlichen Schutz wünschen).

Wenn Sie Django verwenden. Wenn Sie Django verwenden, sollte Folgendes eine sichere Möglichkeit sein, Markdown zu verwenden:

{{ untrusted | markdown:"safe" }}

Ab Django 1.4 ist dies sicher. Wenn Sie das Argument "safe" übergeben, hat Django hat jetzt spezielle Unterstützung, um safe_mode festzulegen und enable_attributes zu deaktivieren. Aktualisieren Sie jedoch unbedingt auf = Django 1.4 oder höher; in früheren Versionen diese Verwendung war unsicher .

16
D.W.

Markdown allein würde nicht ausreichen, um die Ausgabe zu santisieren, da es beliebige HTML/Javascript-Eingaben zulässt und diese einfach unverarbeitet weitergibt.

Z.B. Dies ist ein gültiger Abschlag:

## heading

text

Aber auch das:

## heading

text <script>alert('hello');</script>

Von der Markdown-Syntax-Seite :

Für jedes Markup, das nicht von der Markdown-Syntax abgedeckt wird, verwenden Sie einfach HTML selbst. Es ist nicht erforderlich, ein Vorwort oder eine Abgrenzung vorzunehmen, um anzuzeigen, dass Sie von Markdown zu HTML wechseln. Sie verwenden nur die Tags.

Ich habe gerade einen kurzen Test mit Python-Markdown durchgeführt und es scheint so zu funktionieren.

Angesichts des begrenzten Zeichensatzes, der von der Markdown-Syntax verwendet wird, ist es möglicherweise einfacher, den Zeichensatz zu filtern, den Benutzer bereitstellen können, bevor Sie ihn eingeben zu Markdown (zB so etwas wie a-zA-Z* #+:/&?=-_()>), aber selbst diese könnten ausreichen, um einen Code zu verwirren, der ihn analysiert/codiert ... Ich bin mir also nicht sicher, wie viel Sicherheit Sie allein dadurch erhalten Sie verwenden Markdown.

AKTUALISIEREN:

nach weiteren Recherchen habe ich fand diese Antwort auf SO was durchaus sinnvoll erscheint.

Ich habe dann auch weiter gesucht und den Schalter safe_mode Entdeckt ( hier erwähnt und hier ).

Ein schneller Test scheint recht gut zu funktionieren, könnte aber weitere Forschung verdienen ...

>>> import markdown
>>> markdown.markdown("<script>alert('hello');</script> hello <strong>world</strong>")
u"<script>alert('hello');</script>\n\n<p>hello <strong>world</strong></p>"
>>> markdown.markdown("<script>alert('hello');</script> hello <strong>world</strong>", safe_mode=True)
u'<p>[HTML_REMOVED]</p>\n<p>hello [HTML_REMOVED]world[HTML_REMOVED]</p>'

Vollständiger Optionssatz für safe_mode verfügbar auf der Dokumentationsseite - in dem auch erwähnt wird, dass enable_attributes Aus Sicherheitsgründen auf False gesetzt ist.

13
Yoav Aner