2013-06-04 10 views
5

Sto scrivendo un'app e voglio che gli utenti siano in grado di inserire file python per casi d'angolo. Nella mia testa il modo migliore che posso pensare di fare questo è salvare il loro file su disco e salvare la posizione su un DB, quindi importarlo dinamicamente usando __import__() e quindi eseguirlo. La prima parte della mia domanda è: è questo il modo migliore per farlo?Leggere dinamicamente in un file python ed eseguirlo in modo sicuro

Inoltre, questo porta alcuni problemi di sicurezza piuttosto grandi. C'è un modo per eseguire il loro modulo sotto restrizione? Per non lasciare che veda il file system o qualcosa del genere?

Edit:

L'esecuzione del pitone sarebbe quello di recuperare i dati da un servizio di back-end che è al di fuori del campo di applicazione "normale", quindi non sarebbe una piena applicazione. Potrebbe essere solo una definizione di un protocollo personalizzato.

+2

http://wiki.python.org/moin/SandboxedPython ... stavo per dirlo come risposta ... ma in realtà basta leggere questo articolo ... –

risposta

3

È possibile utilizzare una combinazione dei componenti incorporati compile e exec per l'esecuzione in memoria. Lo svantaggio è che non si ottengono le linee di origine nei traceback.

Non c'è molta speranza in merito alla sicurezza. Anche se si inseriscono filtri ridicolmente restrittivi, come limitare tutto a una singola espressione e rimuovere la maggior parte delle funzioni incorporate, arbitrary code can be executed. Proibire l'accesso al file system o l'accesso ad altre risorse del sistema operativo è difficile anche all'interno di Python, poiché il codice verrebbe eseguito nello stesso processo. Un processo figlio con severe restrizioni (chroot jail, ulimit, ecc.) È una possibilità, ma non è solo un sacco di lavoro, ma esclude anche molti mezzi di interazione con l'applicazione host.

Se l'applicazione viene eseguita localmente e con le stesse autorizzazioni dell'account dell'utente, è probabilmente meglio non preoccuparsi e dare loro più potenza, in quanto non possono fare nulla/molto che non potrebbero fare comunque, e la maggior parte delle restrizioni renderebbe il compito (qualunque esso sia) più difficile/più fastidioso. Se, d'altra parte, il codice viene eseguito su un server o qualcosa del genere, dimentica lo eseguendolo nello stesso processo.

+0

Sono pensando io può generare un'istanza sandboxed di jvm ed eseguire jython al suo interno. In questo modo, posso prendere il codice utente in più di Python. Ha senso? Mi sono imbattuto anche in [pysandbox] (https://github.com/haypo/pysandbox), ma non sono sicuro di quanto sia legittimo. –

+0

@ sir_charles804 Suoni fattibili. Sarei stanco di girare qualcosa del genere, però, molte opportunità di rovinare. Detto questo, vorrei anche ispezionare attentamente qualsiasi progetto di terze parti che lo faccia (come "pysandbox"). – delnan

+0

Sono d'accordo. Penso che se lo farò sarà con una VM. In questo modo mi fido del contenitore.Non ho deciso che questo è il modo in cui permetterò agli utenti di specificare le connessioni per i casi d'angolo o no, ma il tuo contributo è stato molto utile. Grazie! –

0

Si può considerare seguente metodo

class _DynamicModule(object): 
    def __init__(self, name): 
     self._name = name 

    def load(self, code): 
     execdict = {'__builtins__': __builtins__} 
     exec compile(code, '<string>', 'exec') in execdict 
     for key in execdict: 
      if not key.startswith('_'): 
       if not isinstance(execdict[key], str): 
        execdict[key].__module__ = self._name 
       setattr(self, key, execdict[key]) 
     return self 

import sys 
sys.modules['dummy_modules'] = _DynamicModule('dummy_modules').load('print ("!")') 

questo ha ancora abbastanza grandi problemi di sicurezza.

1

si possono fare diverse cose per limitare i poteri (vedi il mio commento su OP)

ma in realtà i miei due centesimi ... basta dare ad ogni utente la propria VM (forse AWS?) ... in questo modo cant rovinare molto ... e puoi sempre riavviarlo ...

un approccio più complicato (ma probabilmente più interessante) sarebbe usare lex/yacc (in python è PLY) e definire la tua lingua (che potrebbe essere un sottoinsieme limitato di python)

Problemi correlati