2008-08-19 27 views
51

Cách tốt nhất để khử trùng đầu vào của người dùng cho một ứng dụng web dựa trên Python là gì? Có một chức năng duy nhất để xóa các ký tự HTML và các ký tự cần thiết khác kết hợp để ngăn chặn một cuộc tấn công XSS hoặc SQL injection không?Vệ sinh đầu vào của người dùng bằng cách sử dụng Python

+9

bạn không nên cố gắng để sửa chữa SQL injection bởi vệ sinh Nếu API cơ sở dữ liệu được sử dụng đúng cách thì không có cơ hội tiêm SQL. –

+2

'... nếu API cơ sở dữ liệu được sử dụng đúng là không có cơ hội tiêm SQL'. Theo đúng, bạn có nghĩa là sử dụng truy vấn tham số? Điều đó có bao gồm bạn 100% không? – Medorator

+2

@ buffer, tôi biết bình luận của bạn là cũ, nhưng nếu bạn muốn những người khác ngoài OP để xem ý kiến ​​của bạn, bạn phải gọi cho họ với một biểu tượng \ @. – user1717828

Trả lời

0

Nếu bạn đang sử dụng một khung như django, khung có thể dễ dàng thực hiện việc này cho bạn bằng cách sử dụng các bộ lọc tiêu chuẩn. Trong thực tế, tôi khá chắc chắn django tự động làm điều đó trừ khi bạn nói nó không.

Nếu không, tôi khuyên bạn nên sử dụng một số loại xác thực regex trước khi chấp nhận đầu vào từ biểu mẫu. Tôi không nghĩ rằng có một viên đạn bạc cho vấn đề của bạn, nhưng bằng cách sử dụng các mô-đun tái, bạn sẽ có thể xây dựng những gì bạn cần.

6

Jeff Atwood mình đã mô tả cách StackOverflow.com sanitizes đầu vào sử dụng (trong điều kiện phi ngôn ngữ cụ thể) trên blog Stack Overflow: http://blog.stackoverflow.com/2008/06/safe-html-and-xss/

Tuy nhiên, khi Justin chỉ ra, nếu bạn sử dụng Django mẫu hoặc một cái gì đó tương tự sau đó họ có thể khử trùng sản lượng HTML của bạn anyway.

SQL injection cũng không phải là một mối quan tâm. Tất cả các thư viện cơ sở dữ liệu của Python (MySQLdb, cx_Oracle, v.v.) luôn luôn khử trùng các tham số mà bạn vượt qua. Các thư viện này được sử dụng bởi tất cả các trình ánh xạ đối tượng-quan hệ của Python (chẳng hạn như các mô hình Django), vì vậy bạn không cần phải lo lắng về vệ sinh ở đó.

24

Dưới đây là một đoạn mã sẽ xóa tất cả các thẻ không có trong danh sách trắng và tất cả các thuộc tính thẻ không nằm trong danh sách trắng được ghi nhận (vì vậy bạn không thể sử dụng onclick).

Đây là phiên bản sửa đổi của http://www.djangosnippets.org/snippets/205/, với regex trên các giá trị thuộc tính để ngăn người dùng sử dụng href="javascript:..." và các trường hợp khác được mô tả tại http://ha.ckers.org/xss.html.
(ví dụ <a href="ja&#x09;vascript:alert('hi')"> hoặc <a href="ja vascript:alert('hi')">, vv)

Như bạn thấy, nó sử dụng (tuyệt vời) BeautifulSoup thư viện.

import re 
from urlparse import urljoin 
from BeautifulSoup import BeautifulSoup, Comment 

def sanitizeHtml(value, base_url=None): 
    rjs = r'[\s]*(&#x.{1,7})?'.join(list('javascript:')) 
    rvb = r'[\s]*(&#x.{1,7})?'.join(list('vbscript:')) 
    re_scripts = re.compile('(%s)|(%s)' % (rjs, rvb), re.IGNORECASE) 
    validTags = 'p i strong b u a h1 h2 h3 pre br img'.split() 
    validAttrs = 'href src width height'.split() 
    urlAttrs = 'href src'.split() # Attributes which should have a URL 
    soup = BeautifulSoup(value) 
    for comment in soup.findAll(text=lambda text: isinstance(text, Comment)): 
     # Get rid of comments 
     comment.extract() 
    for tag in soup.findAll(True): 
     if tag.name not in validTags: 
      tag.hidden = True 
     attrs = tag.attrs 
     tag.attrs = [] 
     for attr, val in attrs: 
      if attr in validAttrs: 
       val = re_scripts.sub('', val) # Remove scripts (vbs & js) 
       if attr in urlAttrs: 
        val = urljoin(base_url, val) # Calculate the absolute url 
       tag.attrs.append((attr, val)) 

    return soup.renderContents().decode('utf8') 

Như các áp phích khác đã nói, khá nhiều tất cả thư viện Python db đều quan tâm đến việc chèn SQL, vì vậy điều này khá nhiều.

+2

Tôi upvoted này, nhưng bây giờ tôi không chắc chắn như vậy. Tôi không nghĩ rằng điều này bảo vệ người dùng IE khỏi src = "vbscript: msgbox ('xss')" tấn công. –

+0

Bạn có thể dễ dàng thêm điều đó với một regex khác cho vbscript: như một đối với javascript: – tghw

+3

Đã thêm bảo vệ VBScript. – tghw

4

tôi không làm phát triển web nhiều nữa, nhưng khi tôi đã làm, tôi đã làm một cái gì đó giống như vậy:

Khi không có phân tích cú pháp là vụ xảy ra, tôi thường chỉ thoát dữ liệu để không can thiệp vào cơ sở dữ liệu khi tôi lưu trữ nó, và thoát khỏi mọi thứ tôi đọc từ cơ sở dữ liệu để không can thiệp vào html khi tôi hiển thị nó (cgi.escape() trong python).

Rất có thể, nếu ai đó cố gắng nhập các ký tự html hoặc nội dung, chúng thực sự muốn được hiển thị dưới dạng văn bản. Nếu họ không, cũng khó khăn :)

Trong ngắn hạn luôn luôn thoát khỏi những gì có thể ảnh hưởng đến mục tiêu hiện tại cho dữ liệu.

Khi tôi cần phân tích cú pháp (đánh dấu hoặc bất kỳ điều gì), tôi thường cố gắng giữ ngôn ngữ đó trong tập hợp không giao nhau với html, vì vậy tôi vẫn có thể lưu trữ nó một cách phù hợp (sau khi xác thực lỗi cú pháp) và phân tích cú pháp html khi hiển thị mà không phải lo lắng về dữ liệu mà người dùng đưa vào đó can thiệp vào html của bạn.

cũng Escaping HTML

12

Xem Cách tốt nhất để ngăn ngừa XSS không phải là để thử và lọc tất cả mọi thứ, nhưng thay vì chỉ đơn giản là làm mã hóa HTML Entity. Ví dụ: tự động chuyển < thành & lt ;. Đây là giải pháp lý tưởng giả sử bạn không cần chấp nhận bất kỳ đầu vào html nào (bên ngoài các khu vực diễn đàn/nhận xét mà nó được sử dụng làm đánh dấu, nó sẽ khá hiếm khi cần chấp nhận HTML); có rất nhiều hoán vị thông qua mã hóa thay thế mà bất cứ điều gì, nhưng một danh sách trắng cực kỳ hạn chế (a-z, A-Z, 0-9 ví dụ) sẽ cho phép một cái gì đó thông qua.

SQL Injection, trái với ý kiến ​​khác, vẫn có thể, nếu bạn chỉ xây dựng một chuỗi truy vấn. Ví dụ, nếu bạn chỉ ghép nối một tham số vào một chuỗi truy vấn, bạn sẽ có SQL Injection. Cách tốt nhất để bảo vệ chống lại điều này cũng không phải là lọc, mà là sử dụng các truy vấn được tham số một cách tôn giáo và KHÔNG BAO GIỜ kết nối đầu vào của người dùng. Đây không phải là để nói rằng lọc không phải là một thực hành tốt nhất, nhưng trong điều khoản của SQL Injection và XSS, bạn sẽ được bảo vệ nhiều hơn nếu bạn tôn giáo sử dụng Parameterize truy vấn và HTML Entity Encoding.

+0

Điều này không đúng trong nhiều trường hợp. Xem ghi chú OSWAP về "Tại sao tôi không thể chỉ HTML thực thể mã hóa dữ liệu không đáng tin cậy?" https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet – Purrell

19

Chỉnh sửa: bleach là trình bao bọc xung quanh html5lib giúp dễ dàng sử dụng hơn với tư cách là một chuyên gia vệ sinh dựa trên danh sách trắng.

html5lib đi kèm với một sanitiser HTML whitelist dựa trên - thật dễ dàng để phân lớp nó để hạn chế các thẻ và các thuộc tính người dùng được phép sử dụng trên trang web của bạn, và nó thậm chí cố gắng để khử trùng CSS nếu bạn cho phép sử dụng các style thuộc tính.

Dưới đây là bây giờ tôi đang sử dụng nó trong chức năng sanitize_html tiện ích bản sao Stack Overflow của tôi:

http://code.google.com/p/soclone/source/browse/trunk/soclone/utils/html.py

Tôi đã ném tất cả các cuộc tấn công được liệt kê trong ha.ckers.org's XSS Cheatsheet (mà là handily available in XML format vào nó sau khi thực hiện Markdown để Chuyển đổi HTML bằng cách sử dụng python-markdown2 và dường như đã được giữ lại ok.

Thành phần trình soạn thảo WMD mà Stackoverflow hiện đang sử dụng là một vấn đề, mặc dù - Tôi thực sự phải tắt JavaScript để kiểm tra XS S Cheatsheet tấn công, như dán tất cả vào WMD đã kết thúc cho tôi hộp cảnh báo và trống ra trang.

2

Để khử trùng đầu vào chuỗi mà bạn muốn lưu trữ vào cơ sở dữ liệu (ví dụ như tên khách hàng), bạn cần thoát hoặc loại bỏ bất kỳ dấu ngoặc kép (',') nào khỏi nó. có thể xảy ra nếu bạn đang lắp ráp một truy vấn SQL từ chuỗi thông qua bởi người sử dụng

Ví dụ (nếu nó có thể chấp nhận để loại bỏ dấu ngoặc kép hoàn toàn):.

datasetName = datasetName.replace("'","").replace('"',"") 
+0

Er ... no ... Tôi sẽ không làm điều này. Đối với tất cả mọi thứ đó là một mục dữ liệu, hãy sử dụng các truy vấn được tham số hóa. Đối với các dữ liệu không (truy vấn được tạo động), bạn thực sự nên sử dụng danh sách trắng. 'pg_catalog.pg_user' không chứa dấu ngoặc kép, nhưng bạn có thể không muốn điều đó trong các truy vấn được tạo ra của bạn. Thay vào đó, hãy làm điều gì đó như 'datasetName = datasetName nếu datasetName trong DATASETNAME_WHITELIST else sulk()' – SingleNegationElimination

Các vấn đề liên quan