Le sandboxing en Python est difficile . Python est intrinsèquement introspectable, à plusieurs niveaux.
Cela signifie également que vous pouvez trouver les méthodes d'usine pour des types spécifiques à partir de ces types eux-mêmes et construire de nouveaux objets de bas niveau, qui seront exécutés directement par l'interpréteur sans limitation.
Voici quelques exemples de solutions créatives pour sortir des sandbox Python:
L'idée de base est toujours de trouver un moyen de créer des types Python de base; fonctions et classes et sortir du shell en obtenant l'interpréteur Python pour exécuter arbitraire (non vérifié!) bytecode.
La même chose et plus s'appliquent à l' exec
instruction ( exec()
fonction en Python 3).
Donc, vous voulez:
Contrôlez strictement la compilation d'octets du code Python, ou au moins post-traitez le bytecode pour supprimer tout accès aux noms commençant par des traits de soulignement.
Cela nécessite une connaissance approfondie du fonctionnement de l'interpréteur Python et de la structure du bytecode Python. Les objets de code sont imbriqués; le bytecode d'un module ne couvre que le niveau supérieur des instructions, chaque fonction et classe se compose de leur propre séquence de bytecode plus des métadonnées, contenant d' autres objets de bytecode pour les fonctions et classes imbriquées, par exemple.
Vous devez ajouter à la liste blanche les modules qui peuvent être utilisés. Soigneusement.
Un module python contient des références à d' autres modules. Si vous importez os
, il y a un nom local os
dans votre espace de noms de module qui fait référence au os
module. Cela peut conduire un attaquant déterminé à des modules qui peuvent les aider à sortir du bac à sable. Le pickle
module, par exemple, vous permet de charger des objets de code arbitraires par exemple, donc si un chemin à travers des modules en liste blanche mène au pickle
module, vous avez toujours un problème.
Vous devez limiter strictement les quotas de temps. Même le code le plus stérilisé peut toujours tenter de s'exécuter indéfiniment, bloquant ainsi vos ressources.
Jetez un œil à RestrictedPython , qui tente de vous donner le contrôle strict du bytecode. RestrictedPython
transforme le code Python en quelque chose qui vous permet de contrôler quels noms, modules et objets sont autorisés dans Python 2.3 à 2.7.
Si RestrictedPython
est suffisamment sécurisé pour vos besoins, cela dépend des politiques que vous implémentez. Ne pas autoriser l'accès aux noms commençant par un trait de soulignement et la liste strictement blanche des modules serait un début.
À mon avis, la seule option vraiment robuste consiste à utiliser une machine virtuelle distincte, sans accès réseau au monde extérieur que vous détruisez après chaque exécution. À la place, chaque nouveau script reçoit une nouvelle machine virtuelle. De cette façon, même si le code parvient à sortir de votre sandbox Python (ce qui n'est pas improbable), tout l'attaquant y accède est de courte durée et sans valeur.