it-swarm-vi.com

Làm cách nào để sử dụng Markdown an toàn?

Làm cách nào để sử dụng thư viện Markdown một cách an toàn? Tôi cần làm gì để đảm bảo rằng đầu ra của nó an toàn để đưa vào trang web của tôi?

Tôi muốn cho phép người dùng không tin cậy nhập nội dung (ở định dạng Markdown). Tôi sẽ sử dụng bộ xử lý Markdown để tạo HTML và tôi muốn đưa HTML đó vào trang web của mình. Tôi cần làm gì để đảm bảo rằng điều này an toàn và không phải là lỗ hổng XSS tự gây ra? Những lý lẽ nào tôi cần phải vượt qua? Có bất kỳ tiền xử lý hoặc hậu xử lý tôi cần phải làm gì? Tôi đang sử dụng thư viện python-markdown, nếu điều đó có liên quan.

45
D.W.

Sử dụng được đề xuất. Câu trả lời ngắn gọn là: Sử dụng markdown(untrusted, safe_mode=remove, enable_attributes=False).

Đảm bảo rằng bạn có phiên bản cập nhật của thư viện Markdown, vì các phiên bản cũ hơn có một số vấn đề về bảo mật.

Bạn cũng có thể chạy đầu ra thông qua trình khử trùng HTML, như Bộ lọc HTML.

Cơ sở lý luận. Nên tắt enable_attributes. Mặc dù các phiên bản phát triển mới nhất của thư viện Python markdown sẽ tắt enable_attributes Theo mặc định nếu bạn đặt safe_mode , các phiên bản trước đó không Do đó, do đó, chỉ cần đặt safe_modekhông đủ trên hầu hết các phiên bản của thư viện Markdown . Nếu bạn chỉ đặt safe_mode, kết quả là không an toàn:

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

Hiện tại, các bản sửa lỗi chỉ hiện diện trong git. Tại thời điểm viết bài này, phiên bản mới nhất được phát hành của Python Markdown (2.1.1) vẫn dễ bị tấn công trừ khi bạn đặt rõ ràng enable_attributes=False. Do đó, có thể có nhiều hệ thống hiện tại bằng cách sử dụng Python Markdown có thể dễ bị tổn thương.

Các tài liệu có thể tốt hơn trong việc cảnh báo người dùng Markdown về những cạm bẫy này. Nó nói những điều như "Bạn cũng có thể muốn đặt enable_attributes=False Khi sử dụng safe_mode", Mà không tiết lộ rằng việc không làm như vậy sẽ tạo ra một lỗ XSS với tất cả các phiên bản mới nhất của thư viện. Các phiên bản sau của tài liệu nói rằng cài đặt enable_attributes "Có khả năng cho phép người dùng không tin cậy tiêm JavaScript vào tài liệu của bạn"; Sẽ rõ ràng hơn khi nói rằng cài đặt enable_attributes sẽ cho phép người dùng đưa Javascript vào tài liệu của bạn và do đó rất không an toàn nếu Markdown có thể đến từ một nguồn không đáng tin cậy.

Nghi ngờ. Điều đó nói rằng, tôi không chắc chắn 100% liệu kết quả có an toàn hay không, ngay cả khi sử dụng nó như được đề xuất ở trên. Các nhà phát triển đã đưa ra ý kiến ​​như sau:

"Chế độ an toàn" là một lựa chọn tên kém mà chúng tôi tiếp tục sử dụng để so sánh ngược (mã cũ vẫn hoạt động với các phiên bản mới hơn). Những gì nó thực sự là một chế độ không đánh dấu. Nói cách khác, đó chỉ là một cách để không cho phép html thô và thực sự không đảm bảo an toàn.

Những bình luận đó hơi đáng sợ.

Trong các phiên bản trước của thư viện Python Markdown, việc khử trùng HTML của nó có vẻ hơi mong manh đối với tôi, vì vậy tôi không chắc liệu tôi có tin tưởng các phiên bản trước của thư viện Markdown hay không, bất kể cờ nào được thông qua. Hãy xem xét những điều sau đây:

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

Cho phép javascript: - URL kiểu thông qua quá trình xử lý của Markdown dường như giống như một quyết định thiết kế đáng ngờ. Cảm giác như đây là một bước nhảy, bỏ qua và nhảy XSS. Tất cả những gì còn thiếu là một cách để thoát ra khỏi nhận xét kiểu C++ (//), Và đó là trò chơi kết thúc. Ví dụ:

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

Tôi tự tin đến mức nào khi không có trình duyệt nào thực thi Javascript đó? Tôi không biết, nhưng nó không mang lại cho tôi cảm giác ấm áp, mờ nhạt. Nếu an toàn, đó chỉ là may mắn mù quáng.

May mắn thay, phiên bản Markdown được phát hành mới nhất dường như thực hiện quá trình lọc tập lệnh chặt chẽ hơn nếu bạn đặt enable_attributes=False. Nhưng hãy đảm bảo bạn đã đặt enable_attributes=False, Nếu không, Markdown sẽ quay trở lại việc khử trùng HTML dễ vỡ được tìm thấy trong các phiên bản trước đó và tôi không tin tưởng vào tính bảo mật của sơ đồ đó.

Điều không nên làm. Sau đây không an toàn: markdown(escape(untrusted)).

  • Bạn có thể nghĩ rằng lần đầu tiên thoát khỏi đầu vào sẽ xóa tất cả HTML và làm cho việc sử dụng này an toàn. Trong thực tế, tôi đã thấy điều này được sử dụng trong một số hệ thống và được một số người khuyên dùng. Tuy nhiên, nó thực sự không an toàn, vì thoát là không đủ để làm cho URL an toàn. Chẳng hạn, việc sử dụng Markdown này có thể bị đánh bại bởi "[clickme](javascript:alert%28%22xss%22%29)". Nói chung, thoát khỏi đầu vào Markdown là không phải là cách tiếp cận đúng ; Cách tiếp cận đúng là gọi Markdown theo cách thích hợp (và có thể áp dụng bộ lọc HTML cho đầu ra của nó, nếu bạn muốn bảo vệ thêm).

Nếu bạn sử dụng Django. Nếu bạn sử dụng Django, sau đây nên là cách an toàn để sử dụng Markdown:

{{ untrusted | markdown:"safe" }}

Kể từ Django 1.4 , điều này là an toàn. khi bạn vượt qua đối số "safe", Django hiện có hỗ trợ đặc biệt để đặt safe_mode và vô hiệu hóa enable_attributes. Nhưng hãy đảm bảo cập nhật thành = Django 1.4 trở lên; trong các phiên bản trước, cách sử dụng này không an toàn .

16
D.W.

Chỉ riêng Markdown sẽ không đủ để tạo ra đầu ra, vì nó cho phép nhập HTML/Javascript tùy ý và chỉ cần chuyển nó chưa được xử lý.

Ví dụ. đây là một đánh dấu hợp lệ:

## heading

text

Nhưng cũng thế này:

## heading

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

Từ trang cú pháp đánh dấ :

Đối với bất kỳ đánh dấu nào không được bao gồm bởi cú pháp Markdown, bạn chỉ cần sử dụng chính HTML. Ở đó, bạn không cần phải mở đầu hoặc phân định nó để chỉ ra rằng bạn đang chuyển từ Markdown sang HTML; bạn chỉ cần sử dụng các thẻ.

Tôi vừa thực hiện một thử nghiệm nhanh bằng cách sử dụng python-markdown và nó dường như hoạt động theo cách này.

Điều đó nói rằng, với bộ ký tự giới hạn được sử dụng theo cú pháp đánh dấu, có thể dễ dàng lọc bộ ký tự bạn cho phép người dùng cung cấp trước bạn cung cấp cho nó để đánh dấu (ví dụ như một cái gì đó như a-zA-Z* #+:/&?=-_()>), nhưng ngay cả những thứ đó có thể đủ để nhầm lẫn một số mã phân tích/mã hóa nó ... Vì vậy, tôi không thực sự chắc chắn rằng bạn nhận được bao nhiêu sự an toàn từ thực tế rằng bạn sử dụng markdown.

CẬP NHẬT:

khi nghiên cứu thêm tôi tìm thấy câu trả lời này trên SO có vẻ khá hợp lý.

Sau đó tôi cũng đã tìm kiếm thêm và phát hiện ra công tắc safe_mode ( được đề cập ở đâytại đây ).

Một bài kiểm tra nhanh dường như hoạt động khá tốt, nhưng nó có thể xứng đáng được nghiên cứu thêm ...

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

Tùy chọn đầy đủ được đặt cho safe_mode có sẵn trên trang tài liệ - cũng đề cập đến việc enable_attributes Được đặt thành False để đảm bảo an toàn.

13
Yoav Aner