tMC*_*tMC 7 python security namespaces pickle
它在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
>>>
Run Code Online (Sandbox Code Playgroud)
谁能解释一下?
module(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
Run Code Online (Sandbox Code Playgroud)
注意这一__import__(module)行.
GLOBAL 'os system'执行pickle字节码指令时调用该函数.
此机制是必要的,以便能够取消其模块尚未显式导入调用方命名空间的类的实例.
如果您使用pickletools.dis来反汇编泡菜,您可以看到它是如何工作的:
import pickletools
print pickletools.dis("cos\nsystem\n(S'ls ~'\ntR.")
Run Code Online (Sandbox Code Playgroud)
输出:
0: c GLOBAL 'os system'
11: ( MARK
12: S STRING 'ls ~'
20: t TUPLE (MARK at 11)
21: R REDUCE
22: . STOP
Run Code Online (Sandbox Code Playgroud)
Pickle使用一个简单的基于堆栈的虚拟机来记录用于重建对象的指令.换句话说,示例中的腌制指令是:
推送self.find_class(module_name,class_name)即推送os.system从最顶层的堆栈项推送字符串'ls~'Build元组在堆栈上应用callable到argtuple.即os.system(*('ls~',))