Il sandboxing di Python è difficile . Python è intrinsecamente introspectable, a più livelli.
Questo significa anche che puoi trovare i metodi di fabbrica per tipi specifici da quei tipi stessi e costruire nuovi oggetti di basso livello, che verranno eseguiti direttamente dall'interprete senza limitazioni.
Ecco alcuni esempi di come trovare modi creativi per abbandonare le sandbox Python:
-
Ned Batchelder inizia con una dimostrazione di come % eval()
pericoloso sia ; eval()
è spesso usato per eseguire espressioni Python; come una sandbox primitiva e ingenua per one-liner.
Ha quindi continuato a provare e applicare gli stessi principi a Python 3 , eventualmente riuscire a scoppiare con alcuni utili suggerimenti.
-
Pierre Bourdon utilizza tecniche simili a hack un sistema python su un hack-a-thon
L'idea di base è sempre quella di trovare un modo per creare tipi Python di base; funzioni e classi e uscire dalla shell ottenendo l'interprete Python per eseguire bytecode arbitrario (non controllato!).
Lo stesso e altro vale per l'istruzione exec
(funzione exec()
in Python 3).
Quindi, vuoi:
-
Controlla rigorosamente la compilazione di byte del codice Python, o almeno post-processa il bytecode per rimuovere qualsiasi accesso ai nomi che iniziano con caratteri di sottolineatura.
Ciò richiede una conoscenza approfondita di come funziona l'interprete Python e di come è strutturato Bytecode Python. Gli oggetti codice sono nidificati; il codice byte di un modulo copre solo il livello più alto delle istruzioni, ogni funzione e classe è costituita dalla propria sequenza bytecode più metadati, contenenti altri oggetti bytecode per funzioni e classi annidate, per esempio.
-
Hai bisogno dei moduli whitelist che possono essere utilizzati. Con attenzione.
Un modulo python contiene riferimenti a altri moduli. Se importi os
, c'è un nome locale os
nello spazio dei nomi del modulo che fa riferimento al modulo os
. Questo può portare un determinato attaccante a moduli che possono aiutarli a uscire dalla sandbox. Il modulo pickle
, ad esempio, ti consente di caricare oggetti di codice arbitrario, ad esempio, quindi se un percorso qualsiasi attraverso i moduli autorizzati conduce al modulo pickle
, hai ancora un problema.
-
È necessario limitare rigorosamente le quote temporali. Anche il codice più castrato può ancora tentare di funzionare per sempre, legando le tue risorse.
Dai un'occhiata a RestrictedPython , che tenta di darti il rigoroso controllo bytecode. RestrictedPython
trasforma il codice Python in qualcosa che ti permette di controllare quali nomi, moduli e oggetti sono permessi in Python 2.3 fino a 2.7.
Se RestrictedPython
è abbastanza sicuro per i tuoi scopi dipende dalle politiche che implementa. Non consentire l'accesso ai nomi che iniziano con un trattino basso e autorizzare rigorosamente la creazione di whitelist dei moduli sarebbe un inizio.
Secondo me, l'unica opzione veramente valida è quella di utilizzare una Virtual Machine separata, una senza accesso alla rete al mondo esterno che distruggi dopo ogni esecuzione. Invece, a ogni nuovo script viene assegnata una nuova VM. In questo modo, anche se il codice riesce a uscire dalla tua sandbox Python (che non è improbabile), tutto ciò a cui l'utente malintenzionato ha accesso è di breve durata e senza valore.