2009-03-19 29 views
22

Nếu tôi đánh giá một chuỗi Python sử dụng eval(), và có một lớp học như:Bảo mật của eval() của Python trên các chuỗi không đáng tin cậy?

class Foo(object): 
    a = 3 
    def bar(self, x): return x + a 

những rủi ro bảo mật nếu tôi không tin tưởng vào chuỗi là gì? Cụ thể:

  1. Có phải eval(string, {"f": Foo()}, {}) không an toàn? Đó là, bạn có thể đạt được os hoặc sys hoặc một cái gì đó không an toàn từ một ví dụ Foo?
  2. Có phải eval(string, {}, {}) không an toàn? Đó là, tôi có thể tiếp cận os hoặc sys hoàn toàn từ nội trang như len và danh sách?
  3. Có cách nào để tạo nội trang không có trong ngữ cảnh eval không?

Có một số chuỗi không an toàn như "[0] * 100000000" Tôi không quan tâm, bởi vì lúc tồi tệ nhất chúng làm chậm/dừng chương trình. Tôi chủ yếu quan tâm đến việc bảo vệ dữ liệu người dùng bên ngoài chương trình.

Rõ ràng, eval(string) không có từ điển tùy chỉnh không an toàn trong hầu hết các trường hợp.

+0

có, nếu có nhập sys sys.dostuff trong chuỗi bạn đang thực hiện đánh giá và bạn không tin tưởng vào chuỗi nội dung có thể trở nên thực sự xấu xí. – Vasil

+0

eval có thuộc tính đẹp, nó chỉ cho phép biểu thức. Vì vậy, những thứ như =, nhập khẩu và in ấn không được phép. –

+6

Hãy thử 'eval ('__ import __ (" sys "). Stdout.write (" Hello Joe ")')' –

Trả lời

13

Bạn không thể bảo mật eval bằng cách tiếp cận danh sách đen như thế này. Xem Eval really is dangerous để biết các ví dụ về đầu vào sẽ phân tách trình thông dịch CPython, cấp quyền truy cập vào bất kỳ lớp nào bạn thích, v.v.

43

eval() sẽ cho phép dữ liệu độc hại xâm phạm toàn bộ hệ thống của bạn, giết mèo, ăn thịt và làm tình với vợ của bạn.

thời gian gần đây có một chủ đề về làm thế nào để làm điều này loại điều an toàn trên danh sách python-dev, và kết luận là:

  • Thật sự rất khó để làm điều này đúng cách.
  • Nó yêu cầu các bản vá lỗi cho trình thông dịch python để chặn nhiều lớp tấn công.
  • Đừng làm điều đó trừ khi bạn thực sự muốn.

Bắt đầu vào đây để đọc về các thách thức: http://tav.espians.com/a-challenge-to-break-python-security.html

tình hình gì bạn muốn sử dụng eval() trong? Bạn có muốn người dùng có thể thực hiện các biểu thức tùy ý không? Hay bạn muốn chuyển dữ liệu theo một cách nào đó? Có lẽ nó có thể khóa đầu vào theo một cách nào đó.

+2

+1: Ai là người độc hại chèn mã độc mà bạn đang eval() - ing? Tìm người đó - nghiêm túc. Hầu hết các 'eval là không an toàn' là giả thuyết vẫy tay về một số người xấu xa mà không ai thực sự có thể xác định. –

+7

@S. Lott - Không phải là một trong những ý tưởng lái xe đằng sau an ninh để ngăn chặn * những điều xấu xảy ra thay vì sau đó hy vọng cả hai có thể xác định kẻ tấn công và thuyết phục họ không làm điều đó một lần nữa? Tại sao không khuyến khích thực hành tốt? –

+2

Bất kỳ tình huống nào mà một người trên internet lớn hơn viết mã không đáng tin cậy để chạy trên hệ thống của bạn yêu cầu những người không tin cậy không thể tấn công. "Ai là người này" - nếu bạn đã viết một cái gì đó không an toàn với eval() và tôi biết? Nó sẽ là tôi để cho bạn thấy bạn không nên làm điều đó. – Jerub

4

Bạn đang có lẽ tốt hơn biến câu hỏi xung quanh:

  1. Những loại biểu thức mà bạn đang muốn eval?
  2. Bạn có thể đảm bảo rằng chỉ các chuỗi khớp với một số cú pháp được xác định hẹp là eval() d?
  3. Sau đó, xem xét nếu rằng là an toàn.

Ví dụ: nếu bạn muốn cho phép người dùng nhập biểu thức đại số để đánh giá, hãy xem xét giới hạn chúng thành một tên biến số, số và tập hợp toán tử và chức năng cụ thể. Đừng đánh dấu() các chuỗi có chứa bất kỳ thứ gì khác.

+0

Hoặc, hãy xem xét điều này: tìm người giữ mã độc hại vào các biểu thức eval của bạn. Giáo dục người đó về hậu quả của hành vi chống đối xã hội của họ. Nghiêm túc. Ai đang đặt mã trong các biểu thức eval? –

+3

@ S.Lott - Nếu anh ta viết các chương trình mật mã, hoặc là Carol hoặc Eve, và để xử lý email [email protected] của nó nhưng tôi không biết liệu chúng tôi có bao giờ nhận ra đó là ai trong trường hợp chung hay không. – MarkusQ

+0

Tôi sẽ đi trước một bước và hỏi * tại sao * bạn muốn làm điều này. –

6

Lưu ý rằng ngay cả khi bạn chuyển các từ điển rỗng vào eval(), vẫn có thể phân tách Python (C) bằng một số thủ thuật cú pháp.Ví dụ: hãy thử thông tin này trên thông dịch viên của bạn: eval("()"*8**5)

+0

Bạn có thể đăng một ví dụ về các thủ thuật đó không? – phihag

+0

Whoa, tại sao điều đó lại gây ra sự xâm nhập? – jacob

+1

Nó tràn ngăn xếp của trình biên dịch. –

9

Bạn có thể truy cập os bằng các hàm dựng sẵn: __import__('os').

Đối với trăn 2.6+, ast module có thể hữu ích; cụ thể là ast.literal_eval, mặc dù nó phụ thuộc vào chính xác những gì bạn muốn đánh giá.

2

Có rất tốt article on the un-safety of eval() trong hướng dẫn Dive into Python của Mark Pilgrim.

trích dẫn từ bài viết này:

Cuối cùng, chúng ta có thể an toàn đánh giá biểu thức Python không tin cậy, đối với một số định nghĩa về “an toàn” mà hóa ra không phải là khủng khiếp hữu ích trong thực đời sống. Sẽ ổn nếu bạn chỉ cần chơi xung quanh và sẽ tốt nếu bạn chỉ bao giờ vượt qua đầu vào đáng tin cậy đó. Nhưng bất cứ điều gì khác chỉ là yêu cầu cho sự cố .

+1

Liên kết không còn hợp lệ. – GingerPlusPlus

+0

@GingerPlusPlus: Cảm ơn, có vẻ như Mark đã chuyển miền của anh ấy. Tôi đã cập nhật các liên kết. –

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