2012-04-24 31 views
7

Nó nêu trong tài liệu Python rằng pickle không an toàn và không nên phân tích cú pháp đầu vào không tin cậy của người dùng. Nếu bạn nghiên cứu điều này; hầu như tất cả các ví dụ đều chứng minh điều này bằng cuộc gọi system() qua số os.system.Hiểu về sự không an toàn Pickle của Python

Không rõ ràng với tôi, cách thức os.system được diễn giải chính xác mà không cần mô-đun os được nhập.

>>> import pickle 
>>> pickle.loads("cos\nsystem\n(S'ls /'\ntR.") # This clearly works. 
bin boot cgroup dev etc home lib lib64 lost+found media mnt opt proc root run sbin selinux srv sys tmp usr var 
0 
>>> dir() # no os module 
['__builtins__', '__doc__', '__name__', '__package__', 'pickle'] 
>>> os.system('ls /') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'os' is not defined 
>>> 

Ai đó có thể giải thích?

Trả lời

9

Tên của module (os) là một phần của các opcode, và pickle tự động nhập các module:

# pickle.py 
def find_class(self, module, name): 
    # Subclasses may override this 
    __import__(module) 
    mod = sys.modules[module] 
    klass = getattr(mod, name) 
    return klass 

Lưu ý dòng __import__(module).

Hàm này được gọi khi lệnh GLOBAL 'os system' pickle bytecode được thực hiện.

Cơ chế này là cần thiết để có thể bỏ tạm thời các phiên bản của các lớp có mô-đun chưa được nhập rõ ràng vào không gian tên của người gọi.

+1

+1 để tìm mã mô-đun – tMC

2

Nhập một module chỉ thêm nó vào không gian tên địa phương, mà không nhất thiết phải là một trong những bạn đang ở Trừ khi nó không:.

>>> dir() 
['__builtins__', '__doc__', '__name__', '__package__'] 
>>> __import__('os') 
<module 'os' from '/usr/lib64/python2.7/os.pyc'> 
>>> dir() 
['__builtins__', '__doc__', '__name__', '__package__'] 
6

Nếu bạn sử dụng pickletools.dis để tháo rời các dưa bạn có thể xem cách này đang làm việc:

import pickletools 
print pickletools.dis("cos\nsystem\n(S'ls ~'\ntR.") 

Output:

0: c GLOBAL  'os system' 
11: ( MARK 
12: S  STRING  'ls ~' 
20: t  TUPLE  (MARK at 11) 
21: R REDUCE 
22: . STOP 

Pickle sử dụng một máy ảo dựa trên stack đơn giản ghi lại các hướng dẫn được sử dụng để tái tạo lại đối tượng. Nói cách khác các hướng dẫn ngâm trong ví dụ của bạn là:

Đẩy self.find_class (module_name, class_name) tức là đẩy os.system Đẩy chuỗi 'ls ~' Build tuple từ mục ngăn xếp trên cùng Áp dụng callable để argtuple, cả trên stack. tức là os.system (* ('ls ~',))

Source

+2

Có, nhưng tại sao điều này không yêu cầu 'nhập os'? – NPE

+1

dir() cố gắng cung cấp một bộ tên thú vị hơn là cố gắng cung cấp một bộ tên được xác định chặt chẽ hoặc nhất quán, và hành vi chi tiết của nó có thể thay đổi qua các bản phát hành. Khi bạn nhập một mô-đun động, không có sự đảm bảo nào bạn sẽ thấy nó với dir() –

8

Đối hoàn toàn quá nhiều thông tin về văn bản Pickles độc hại mà đi xa hơn các os.system tiêu chuẩn() Ví dụ, hãy xem presentation và của nó kèm theo paper.

+1

+1 để tìm kiếm tài nguyên phong phú – gauden

+0

tìm kiếm tuyệt vời- cảm ơn – tMC

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