2012-04-24 15 views
7

En la documentación de Python indica que pickle no es seguro y no debe analizar las entradas de usuario no confiables. Si investigas esto; casi todos los ejemplos lo demuestran con una llamada system() a través del os.system.Comprender la inseguridad de Python Pickle

Lo que no me queda claro, es cómo se interpreta os.system correctamente sin importar el módulo 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 
>>> 

¿Alguien me puede explicar?

Respuesta

9

El nombre del módulo (os) forma parte del código de operación, y pickle importa automáticamente el módulo:

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

Nota la línea __import__(module).

La función se invoca cuando se ejecuta la instrucción de bytecode de picking GLOBAL 'os system'.

Este mecanismo es necesario para poder desmantelar instancias de clases cuyos módulos no se han importado explícitamente en el espacio de nombres de la persona que llama.

+1

+1 para encontrar el código del módulo – tMC

2

Importación de un módulo sólo se añade al espacio de nombres local, que no es necesariamente la que estás en Excepto cuando no es así:.

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

Si utiliza pickletools.dis desmontar la salmuera se puede ver cómo esto está funcionando:

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

salida:

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

Pickle utiliza una máquina virtual simple basada en pila que registra las instrucciones utilizadas para reconstruir el objeto. En otras palabras, las instrucciones en vinagre en el ejemplo son:

empuje self.find_class (module_name, class_name) es decir, empujar os.system Empuje la cadena 'ls ~' tupla Generar a partir de los elementos más altas de la pila Aplicar exigible a argtuple, ambos en la pila. es decir os.system (* ('ls ~',))

Source

+2

Sí, pero ¿por qué esto no requiere 'import os'? – NPE

+1

dir() intenta proporcionar un conjunto de nombres interesante más de lo que intenta proporcionar un conjunto de nombres riguroso o consistentemente definido, y su comportamiento detallado puede cambiar a lo largo de las versiones. Cuando importa un módulo dinámicamente, no hay garantía de que lo verá con dir() –

8

Por completo demasiada información sobre la escritura de las salmueras maliciosos que van mucho más allá que el ejemplo os.system estándar(), ven esto y presentation su acompañante paper.

+1

+1 para desenterrar un recurso enriquecido – gauden

+0

asombroso hallazgo- gracias – tMC

Cuestiones relacionadas