2012-04-24 15 views
7

Indica nella documentazione di Python che pickle non è sicuro e non deve analizzare l'input dell'utente non attendibile. Se si ricerca questo; quasi tutti gli esempi lo dimostrano con una chiamata system() tramite os.system.Informazioni su Python Pickle Insecurity

Non è chiaro per me, è come os.system viene interpretato correttamente senza il modulo os importato.

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

Qualcuno può spiegare?

risposta

9

Il nome del modulo (os) fa parte del codice operativo, e pickle importa automaticamente il modulo:

# 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 linea __import__(module).

La funzione viene richiamata quando viene eseguita l'istruzione bytecode GLOBAL 'os system'.

Questo meccanismo è necessario per poter annullare l'inclusione di istanze di classi i cui moduli non sono stati importati esplicitamente nello spazio dei nomi del chiamante.

+1

+1 per trovare il codice modulo – tMC

2

Importazione di un modulo aggiunge solo per lo spazio dei nomi locale, che non è necessariamente quello che sei in Tranne quando non è così:.

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

Se si utilizza pickletools.dis di smontare la salamoia si può vedere come questo funziona:

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

uscita:

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

Pickle utilizza una semplice macchina virtuale basata su stack che registra le istruzioni utilizzate per ricostruire l'oggetto. In altre parole, le istruzioni salamoia negli esempi sono:

push self.find_class (nome_modulo, nome_classe) vale a dire spingere os.system Spingere le 'ls ~' stringa Corporatura tuple da più in alto gli elementi dello stack Applicare callable a argtuple, entrambi in pila. cioè os.system (* ('ls ~',))

Source

+2

Sì, ma perché non richiede "import os'? – NPE

+1

dir() prova a fornire un insieme interessante di nomi più di quello che prova a fornire un insieme di nomi rigorosamente o coerentemente definito, e il suo comportamento dettagliato può cambiare tra le versioni. Quando si importa dinamicamente un modulo, non vi è alcuna garanzia che lo si vedrà con dir() –

8

Per tutto troppe informazioni sulla scrittura Pickles maligni che vanno ben oltre l'esempio os.system standard(), vedono questo presentation e il suo accompagnamento paper.

+1

+1 per scavare una risorsa ricca – gauden

+0

find fantastico, grazie – tMC