it-swarm-id.com

Bagaimana cara saya menggunakan Markdown dengan aman?

Bagaimana cara menggunakan perpustakaan Markdown dengan aman? Apa yang harus saya lakukan untuk memastikan bahwa outputnya aman untuk dimasukkan ke halaman web saya?

Saya ingin mengizinkan pengguna yang tidak dipercaya untuk memasukkan konten (dalam format Penurunan harga). Saya akan menggunakan prosesor Markdown untuk menghasilkan HTML, dan saya ingin memasukkan HTML itu di halaman web saya. Apa yang harus saya lakukan untuk memastikan ini aman, dan bukan kerentanan XSS yang ditimbulkan sendiri? Argumen apa yang perlu saya sampaikan? Apakah ada preprocessing atau postprocessing yang perlu saya lakukan? Saya menggunakan pustaka python-markdown, jika itu relevan.

45
D.W.

Penggunaan yang disarankan. Jawaban singkatnya adalah: Gunakan markdown(untrusted, safe_mode=remove, enable_attributes=False).

Pastikan Anda memiliki versi terbaru dari perpustakaan Markdown, karena versi yang lebih lama memiliki beberapa masalah keamanan.

Anda juga bisa menjalankan output melalui pembersih HTML, seperti HTML Purifier.

Dasar Pemikiran Adalah ide bagus untuk menonaktifkan enable_attributes. Sementara versi pengembangan terbaru dari perpustakaan markdown Python akan nonaktifkan enable_attributes Secara default jika Anda mengatur safe_mode , versi sebelumnya tidak lakukan itu. Akibatnya, hanya pengaturan safe_mode adalah tidak cukup pada sebagian besar versi perpustakaan Markdown . Jika Anda hanya mengatur safe_mode, hasilnya tidak aman:

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

Saat ini, perbaikan hanya ada di git. Pada saat penulisan ini, versi terbaru yang dirilis Python Markdown (2.1.1) tetap rentan kecuali Anda secara eksplisit menetapkan enable_attributes=False. Oleh karena itu, masuk akal bahwa banyak sistem saat ini menggunakan Python Penurunan harga mungkin rentan.

Dokumentasi bisa lebih baik dalam memperingatkan pengguna Markdown tentang jebakan ini. Ia mengatakan hal-hal seperti "Anda mungkin juga ingin mengatur enable_attributes=False Ketika menggunakan safe_mode", Tanpa mengungkapkan bahwa gagal melakukannya menciptakan lubang XSS dengan semua kecuali versi terbaru dari perpustakaan. Versi dokumentasi selanjutnya mengatakan bahwa pengaturan enable_attributes "Berpotensi memungkinkan pengguna yang tidak tepercaya menyuntikkan JavaScript ke dalam dokumen Anda"; akan lebih jelas untuk mengatakan bahwa pengaturan enable_attributes memungkinkan pengguna untuk menyuntikkan Javascript ke dokumen Anda dan karenanya sangat tidak aman jika penurunan harga mungkin berasal dari sumber yang tidak dipercaya.

Keraguan. Yang mengatakan, saya tidak 100% yakin apakah hasilnya akan aman, bahkan ketika menggunakannya seperti yang direkomendasikan di atas. Pengembang telah membuat komentar seperti berikut:

"safe-mode" adalah pilihan nama yang buruk yang kami terus gunakan untuk komparabilitas mundur (kode lama masih bekerja dengan versi kami yang lebih baru). Apa itu sebenarnya adalah mode tanpa markup. Dengan kata lain, ini hanya cara untuk tidak mengizinkan html mentah dan benar-benar tidak menjamin keamanan.

Komentar seperti itu agak menakutkan.

Dalam versi sebelumnya dari perpustakaan Markdown Python, sanitasi HTML-nya terlihat agak rapuh bagi saya, jadi saya tidak yakin apakah saya akan mempercayai versi sebelumnya dari perpustakaan Markdown, terlepas dari flag apa disahkan. Pertimbangkan hal berikut:

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

Mengizinkan javascript: - URL gaya melalui pemrosesan Markdown menurut saya seperti keputusan desain yang cukup meragukan. Rasanya seperti ini ada dalam hop, skip, dan jump XSS. Semua yang hilang adalah cara untuk keluar dari komentar gaya C++ (the //), Dan ini sudah berakhir. Contohnya:

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

Seberapa percaya diri saya bahwa tidak ada browser yang akan menjalankan Javascript itu? Saya tidak tahu, tetapi itu tidak memberi saya perasaan hangat dan tidak jelas. Jika aman, itu hanya keberuntungan buta.

Untungnya, versi terbaru dari Markdown tampaknya melakukan penyaringan skrip yang lebih ketat jika Anda mengatur enable_attributes=False. Tetapi pastikan Anda menetapkan enable_attributes=False, Jika tidak, Markdown akan kembali ke sanitasi HTML yang rapuh yang ditemukan di versi sebelumnya, dan saya tidak yakin dengan keamanan skema itu.

Apa yang tidak boleh dilakukan. Berikut ini tidak aman: markdown(escape(untrusted)).

  • Anda mungkin berpikir bahwa melarikan diri dari input akan menghapus semua HTML dan membuat penggunaan ini aman. Sebenarnya saya telah melihat ini digunakan dalam beberapa sistem dan direkomendasikan oleh beberapa. Namun, sebenarnya tidak aman, karena melarikan diri tidak cukup untuk membuat URL aman. Misalnya, penggunaan Markdown ini dapat dikalahkan oleh "[clickme](javascript:alert%28%22xss%22%29)". Secara umum, menghindari input ke penurunan harga adalah bukan pendekatan yang tepat ; pendekatan yang tepat adalah dengan memanggil Markdown dengan cara yang sesuai (dan mungkin juga menerapkan filter HTML pada hasilnya, jika Anda menginginkan perlindungan tambahan).

Jika Anda menggunakan Django. Jika Anda menggunakan Django, berikut ini cara yang aman untuk menggunakan penurunan harga:

{{ untrusted | markdown:"safe" }}

Sampai Django 1.4 , ini aman. ketika Anda melewati argumen "safe", Django sekarang memiliki dukungan khusus untuk mengatur safe_mode dan menonaktifkan enable_attributes. Tetapi pastikan untuk memperbarui ke = Django 1.4 atau lebih tinggi; dalam versi sebelumnya, penggunaan ini tidak aman .

16
D.W.

Penurunan harga saja tidak akan cukup untuk menyuarakan output, karena memungkinkan input HTML/Javascript sewenang-wenang dan hanya meneruskannya tanpa diproses.

Misalnya. ini adalah penurunan harga yang valid:

## heading

text

Tetapi juga ini:

## heading

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

Dari halaman sintaks markdown :

Untuk markup apa pun yang tidak tercakup oleh sintaks Markdown, Anda cukup menggunakan HTML itu sendiri. Tidak perlu untuk kata pengantar atau membatasi untuk menunjukkan bahwa Anda beralih dari penurunan harga ke HTML; Anda hanya menggunakan tag.

Saya baru saja melakukan tes cepat menggunakan python-markdown dan sepertinya berhasil seperti ini.

Yang mengatakan, mengingat set karakter terbatas yang digunakan oleh sintaks markdown, mungkin lebih mudah untuk menyaring set karakter yang Anda izinkan pengguna sediakan sebelum Anda memberinya makan untuk penurunan harga (mis. sesuatu seperti a-zA-Z* #+:/&?=-_()>), tetapi bahkan itu mungkin cukup untuk membingungkan beberapa kode yang mem-parsing/mengkodekannya ... Jadi saya tidak benar-benar yakin berapa banyak keamanan yang Anda dapatkan murni dari kenyataan bahwa Anda menggunakan penurunan harga.

MEMPERBARUI:

setelah penelitian lebih lanjut I menemukan jawaban ini pada SO yang tampaknya cukup masuk akal.

Saya kemudian mencari lebih jauh dan menemukan saklar safe_mode ( disebutkan di sini dan di sini ).

Tes cepat tampaknya bekerja dengan cukup baik, tetapi mungkin perlu penelitian lebih lanjut ...

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

Opsi lengkap disetel untuk safe_mode tersedia di halaman dokumentasi - yang juga menyebutkan enable_attributes Diset ke False untuk keamanan.

13
Yoav Aner