2009-08-29 17 views
10

Estoy escribiendo una aplicación donde los usuarios pueden ingresar un script de python y ejecutarlo en un entorno limitado. Necesito una forma de evitar que el código ejecutado importe ciertos módulos, por lo que el código malicioso no será un gran problema. ¿Hay alguna manera de hacer esto en Python?¿Evitar que el código de Python importe ciertos módulos?

Respuesta

0

Puede sobrecargar el mecanismo de importación. Usamos esto para tener un sistema de licencias para complementos, puede tener fácilmente una lista blanca/lista negra de nombres de módulos.

+8

Esta respuesta necesita un ejemplo para ser útil – Schollii

1

Desafortunadamente, creo que lo que estás tratando de hacer es fundamentalmente imposible. Si los usuarios pueden ejecutar código arbitrario en su aplicación, entonces pueden hacer lo que quieran. Incluso si pudieras evitar que importen ciertos módulos, no habría nada que les impida escribir ellos mismos la funcionalidad equivalente (desde cero o utilizando algunos de los módulos que están disponibles).

Realmente no conozco los detalles de implementar un sandbox en Python, pero me imagino que es algo que debe hacerse a nivel de intérprete y no es nada fácil.

+0

lo que está tratando de hacer es extremadamente difícil, pero no imposible. Si diseña lo suficientemente bien en torno a lo que está haciendo, puede obstaculizar el acceso a su backend y limitarlo, dando acceso solo a lo que se permite ver, y restringir el acceso a las implementaciones hacky que permite python. (hay muchas áreas de restricción que deben cubrirse, desde espacios de nombres de back-end privados hasta operaciones con variables restringidas) – Tcll

13

¿Has comprobado el python.org article on SandboxedPython y el linked article?

Ambas páginas tienen enlaces a otros recursos.

Específicamente, PyPi's RestrictedPython le permite definir exactamente lo que está disponible, y tiene algunos valores predeterminados 'seguros' para elegir.

+0

Debería haber mencionado, mi aplicación se ejecuta en Google App Engine. Así que, por un lado, ya tengo muchos sandboxing en su lugar, pero OTOH no estoy seguro de poder usar RestrictedPython. Sin duda lo intentaré, ¡gracias! –

7

El código abierto de Google App Engine SDK tiene una implementación detallada y sólida de mecanismos para detener la importación de módulos no deseados (para ayudar a detectar código intentando importar módulos que no están disponibles en las instancias de producción de App Engine), aunque incluso eso podría ser subvertido si el código de usuario fuera malvado en lugar de simplemente erróneo (las instancias de producción obviamente tienen más capas de defensa, como simplemente no tener esos módulos cerca ;-).

Por lo tanto, todo depende de cuán en profundidad necesite su defensa. En un extremo, simplemente esconde el builtin __import__ en otro lugar y lo reemplaza con su función que realiza todas las comprobaciones que desea antes de delegar al __builtin__; eso es quizás 20 líneas de código, 30 minutos para implementar y probar a fondo ... pero puede que no lo proteja por mucho tiempo si alguien le ofreció un millón de dólares para entrar en su sistema (y, hipotéticamente, yo no era el goody-two-shoes tipo de chico que en realidad soy, por supuesto ;-). En el otro extremo, despliega una serie de capas de defensa en profundidad que podrían tomar miles de líneas y semanas de implementación y pruebas, dado el tipo de presupuesto de recursos con el que seguramente podría implementar algo I no podría penetrar (¡pero siempre existe el riesgo de que alguien más sea más inteligente y más astuto que yo, por supuesto!).

Entonces, ¿qué tan profundo quieres ir, o mejor dicho, qué tan profundo puedes PERMITIR ir ...?

+0

Estoy lejos de los requisitos/presupuesto del nivel de la NSA, así que supongo que optaría por anular __import__ y si contrata al autor de The Python Cookbook un millón de dólares para romper la protección, solo tendrá las consecuencias .. Cualquier sugerencia a cómo hacer eso? Siendo relativamente nuevo en Python, parece que no puedo encontrar una solución simple. Gracias! –

+0

Las instancias de producción de App Engine están sólidamente protegidas, como dije con muchas capas de defensa: no sabría cómo entrar en ESAS (si lo hiciera, lo comunicaría en privado a mi jefe, o a mis amigos) que trabajan en el equipo de App Engine, por lo que la fuga se solucionará inmediatamente después de que lo descubrí ;-). Solo tenga en cuenta que al igual que su código puede anular el 'import_importar' integrado, también lo hará el código que está importando, por lo tanto, defiéndase contra ESO también; Y, utilice una posición de "denegación predeterminada", donde solo se permiten módulos específicos, en lugar de los específicos. -) –

+0

Suponiendo que el código cuestionable se agrega al programa en ejecución como una cadena que el programa "ejecutará", wouldn ¿No es posible que este código importe nuevos módulos si el programa se incluyó en el instalador de juegos, y por lo tanto no tiene acceso a los módulos que no son importados por el programa principal porque los archivos no están incluidos en el ejecutable? –

18

Si pones Ninguno en sys.modules para un nombre de módulo, en el que no habrá importables ...

>>> import sys 
>>> import os 
>>> del os 
>>> sys.modules['os']=None 
>>> import os 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ImportError: No module named os 
>>> 
+1

Esto también funciona antes de importar el módulo real. –

+1

@DoktoroReichard Ermm ..., eso es lo que está demostrando ('del os') ... – idmean

0

8 años, yeesh, y nadie se ha dado cuenta de esto uno? :/

Puede anular la instrucción import o también la función .

esto es sólo un garabato de código probado porque no podía encontrar ninguna referencia de fiar:

import importlib 

def secure_importer(name, globals=None, locals=None, fromlist=(), level=0): 

    if name != 'C': print(name, fromlist, level) 

    # not exactly a good verification layer 
    frommodule = globals['__name__'] if globals else None 
    if name == 'B' and frommodule != 'C': 
     raise ImportError("module '%s' is restricted."%name) 

    return importlib.__import__(name, globals, locals, fromlist, level) 

__builtins__.__dict__['__import__'] = secure_importer 

import C 

y aquí las pruebas de ese código:

Python 3.4.3 |Anaconda 2.3.0 (32-bit)| (default, Mar 6 2015, 12:08:17) [MSC v.1600 32 bit (Intel)] on win32 
Type "copyright", "credits" or "license()" for more information. 
>>> ================================ RESTART ================================ 
>>> 
B ('f',) 0 
imported secure module 
>>> from B import f 
B ('f',) 0 
linecache None 0 
encodings.utf_8 ['*'] 0 
Traceback (most recent call last): 
    File "<pyshell#0>", line 1, in <module> 
    from B import f 
    File "\home\tcll\Projects\python\test\restricted imports\main.py", line 11, in secure_importer 
    raise ImportError("module '%s' is restricted."%name) 
ImportError: module 'B' is restricted. 
>>> import C 
>>> 

Por favor, no haga comentarios acerca de mí usando Python34, tengo mis razones, y es mi intérprete principal en Linux específicamente para probar cosas (como el código anterior) para mi proyecto principal.

Cuestiones relacionadas