了解Python的泡菜不安全(Understanding Python Pickle Insecur

2019-06-23 22:08发布

它指出Python文档,在pickle不安全,不应该解析不可信的用户输入。 如果你研究这一点; 几乎所有的例子证明这一点与system()通过调用os.system

什么我不清楚,是如何os.system被正确地解释,而不os模块被导入。

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

有人能解释一下吗?

Answer 1:

该模块的名称( os )是操作码的一部分,并且pickle自动导入模块:

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

注意__import__(module)线。

的当调用该函数时GLOBAL 'os system'被执行咸菜字节代码指令。

这种机制是必要的,以便能够unpickle类,其模块没有明确导入到呼叫者的名字空间的实例。



Answer 2:

有关编写恶意酱菜是走得更远比标准使用os.system()例子干脆太多的信息,请参阅本演示和与之配套的纸 。



Answer 3:

如果您使用pickletools.dis拆卸泡菜你可以看到这是如何工作的:

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

输出:

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

味酸使用其记录用于重建对象的指令的简单的基于堆栈的虚拟机。 换句话说在你的榜样腌渍指令是:

推self.find_class(MODULE_NAME,CLASS_NAME),即推动使用os.system推弦“LS〜”创建一个从最顶层的栈项元组应用调用到argtuple,无论是在栈。 即使用os.system(*( 'LS〜',))

资源



Answer 4:

导入模块只把它添加到局部命名空间,这不一定是你是我的唯一不同之处时,它没有。:

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


文章来源: Understanding Python Pickle Insecurity