it-swarm-eu.dev

Jak mohu Markdown používat bezpečně?

Jak mohu bezpečně používat knihovnu Markdown? Co musím udělat, abych se ujistil, že jeho výstup lze bezpečně začlenit do mé webové stránky?

Chci povolit nedůvěryhodným uživatelům zadávat obsah (ve formátu Markdown). Generuji HTML pomocí procesoru Markdown a rád bych tento HTML vložil do své webové stránky. Co musím udělat, abych se ujistil, že je to bezpečné a že nejde o zranitelnost XSS způsobenou samy sebou? Jaké argumenty musím předat? Musím udělat nějaké předzpracování nebo dodatečné zpracování? Používám knihovnu python-markdown, pokud je to relevantní.

45
D.W.

Doporučené použití Krátká odpověď zní: Použijte markdown(untrusted, safe_mode=remove, enable_attributes=False).

Ujistěte se, že máte aktuální verzi knihovny Markdown, protože starší verze mají určité bezpečnostní problémy.

Výstup můžete také spustit pomocí sanitizéru HTML, jako je HTML Purifier.

Odůvodnění Je dobré zakázat enable_attributes. Zatímco nejnovější vývojové verze knihovny Python markdown library = deaktivují enable_attributes Ve výchozím nastavení, pokud nastavíte safe_mode , dřívější verze neudělal to. V důsledku toho je nastavení safe_modena většině verzí knihovny Markdown nestačí . Pokud nastavíte safe_mode, Výsledek je nejistý:

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

Momentálně jsou opravy přítomny pouze v gitu. V době psaní tohoto dokumentu zůstává poslední vydaná verze Python Markdown (2.1.1)) zranitelná, pokud explicitně nenastavíte enable_attributes=False. Proto je pravděpodobné, že v současné době mnoho systémů using Python Markdown může být zranitelný).

Dokumentace by mohla být lepší pro varování uživatelů Markdown o těchto nástrahách. Říká například „Možná budete chtít nastavit enable_attributes=False, Když používáte safe_mode“, Aniž byste prozradili, že pokud tak neučiníte, vytvoří se XSS díra se všemi, ale nejaktuálnějšími verzemi knihovny. Pozdější verze dokumentace uvádějí, že nastavení enable_attributes "By potenciálně mohlo nedůvěryhodnému uživateli umožnit vložit do vašich dokumentů JavaScript"; Bylo by jasnější říci, že nastavení enable_attributes neumožňuje uživatelům vložit do vašich dokumentů Javascript, a je tedy vysoce nejisté, pokud by Markdown mohl pocházet z nedůvěryhodného zdroje.

Pochybnosti To znamená, že si nejsem stoprocentně jistý, zda bude výsledek bezpečný, i když se použije výše uvedeným způsobem. Vývojáři přidali následující komentáře:

„bezpečný režim“ byl špatný výběr názvu, který nadále používáme pro zpětnou porovnatelnost (starý kód stále funguje s našimi novějšími verzemi). Ve skutečnosti jde o režim bez označení. Jinými slovy, je to jen způsob, jak zakázat surový html a opravdu nezaručuje bezpečnost.

Tyto komentáře jsou trochu děsivé.

V dřívějších verzích knihovny Python Markdown) vypadá její sanitace HTML trochu křehkou, takže si nejsem jistý, zda důvěřuji dřívějším verzi knihovny Markdown, bez ohledu na to, jaké příznaky jsou považovány za:

>>> 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>'

Povolení javascript: - URL stylů prostřednictvím Markdownova zpracování se mi zdá jako docela pochybné návrhové rozhodnutí. Vypadá to, že se jedná o skok, skok a skok XSS. Vše, co chybí, je způsob, jak se vymanit z komentáře ve stylu C++ (//) A je konec hry. Například:

>>> 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>'

Jak jsem si jistý, že žádný prohlížeč nevykoná tento Javascript? Nevím, ale nedává mi teplé, nejasné pocity. Pokud je to bezpečné, je to jen slepé štěstí.

Naštěstí se zdá, že poslední vydaná verze Markdown zpřísňuje filtrování skriptu, pokud nastavíte enable_attributes=False. Ujistěte se však, že jste nastavili enable_attributes=False, Jinak se Markdown vrátí k křehké dezinfekci HTML nalezené v dřívějších verzích a nejsem si jistý v zabezpečení tohoto schématu.

Co dělat Následující není bezpečné: markdown(escape(untrusted)).

  • Možná si myslíte, že první únik ze vstupu by odstranil veškerý HTML a toto použití by bylo bezpečné. Ve skutečnosti jsem to viděl v některých systémech a některé doporučil. Ve skutečnosti je však nebezpečný, protože unikání nestačí k zajištění bezpečných adres URL. Například, toto použití Markdown může být porazeno "[clickme](javascript:alert%28%22xss%22%29)". Obecně je únik vstupu do Markdown není správný přístup ; správným přístupem je vyvolat Markdown vhodným způsobem (a pokud chcete další ochranu, můžete také použít filtr HTML na jeho výstup).

Pokud používáte Django. Pokud používáte Django, mělo by být bezpečným způsobem použití Markdown následující:

{{ untrusted | markdown:"safe" }}

Od Django 1.4 je to bezpečné. když předáte argument "safe", Django má nyní speciální podporu pro nastavení safe_mode a deaktivaci enable_attributes. Nezapomeňte však aktualizovat na = Django 1,4 nebo novější; v dřívějších verzích toto použití bylo nezabezpečené .

16
D.W.

Samotné označení by nestačilo k santizaci výstupu, protože umožňuje libovolný vstup HTML/Javascript a jednoduše jej předává nezpracované.

Např. toto je platné markdown:

## heading

text

Ale také toto:

## heading

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

Ze stránky syntaktická stránka markdown :

U všech značek, na které se syntaxe Markdown nevztahuje, stačí použít samotný HTML. Není třeba jej předmluvovat ani ohraničovat, což znamená, že přecházíte z Markdown na HTML; stačí použít značky.

Právě jsem udělal rychlý test pomocí python-markdown a zdá se, že to tak funguje.

To znamená, že vzhledem k omezené sadě znaků, která se používá při syntaxi markdown, může být snazší filtrovat znakovou sadu, kterou uživatelé mohou poskytnout před , než ji nakrmíte k markdown (např. něco jako a-zA-Z* #+:/&?=-_()>), ale i ty by mohly stačit k zaměnění nějakého kódu, který jej analyzuje/kóduje ... Takže si nejsem opravdu jistý, kolik bezpečnosti dostanete čistě ze skutečnosti, že používáte markdown.

AKTUALIZACE:

po dalším výzkumu jsem našel tuto odpověď na SO což se zdá docela rozumné.

Pak jsem také prohledal další a objevil přepínač safe_mode ( zde zmíněn a zde ).

Rychlý test vypadá docela dobře, ale může si zasloužit další výzkum ...

>>> 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>'

Kompletní sada možností pro safe_mode k dispozici na stránce dokumentace - což také zmiňuje, že z důvodu bezpečnosti byl enable_attributes Nastaven na False.

13
Yoav Aner