它指出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
>>>
有人能解释一下吗?
该模块的名称( 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类,其模块没有明确导入到呼叫者的名字空间的实例。
有关编写恶意酱菜是走得更远比标准使用os.system()例子干脆太多的信息,请参阅本演示和与之配套的纸 。
如果您使用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〜',))
资源
导入模块只把它添加到局部命名空间,这不一定是你是我的唯一不同之处时,它没有。:
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__']
>>> __import__('os')
<module 'os' from '/usr/lib64/python2.7/os.pyc'>
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__']