2009-03-19 9 views
22

Si estoy evaluando una cadena Python usando eval(), y tengo una clase como:Security of Python's eval() en cadenas no confiables?

class Foo(object): 
    a = 3 
    def bar(self, x): return x + a 

¿Cuáles son los riesgos de seguridad si no confían en la cuerda? En particular:

  1. ¿Es inseguro eval(string, {"f": Foo()}, {})? Es decir, ¿puede llegar a os o sys o algo inseguro desde una instancia de Foo?
  2. ¿eval(string, {}, {}) no es seguro? Es decir, ¿puedo llegar a os o sys por completo desde edificios como len y list?
  3. ¿Hay alguna manera de hacer que las construcciones internas no estén presentes en el contexto de evaluación?

Hay algunas cadenas inseguras como "[0] * 100000000" No me importa, porque en el peor de los casos ralentiza/detiene el programa. Me preocupa principalmente proteger los datos del usuario externos al programa.

Obviamente, eval(string) sin diccionarios personalizados es inseguro en la mayoría de los casos.

+0

sí, si hay importación sys sys.dostuff en la cadena que está haciendo eval y usted no confía en las cuerdas, las cosas pueden ponerse realmente feas. – Vasil

+0

eval tiene la propiedad agradable solo permite expresiones. Entonces cosas como =, importar e imprimir no están permitidas. –

+6

Pruebe 'eval ('__ import __ (" sys "). Stdout.write (" Hola Joe ")')' –

Respuesta

13

No se puede asegurar eval con un enfoque de lista negra como este. Consulte Eval really is dangerous para obtener ejemplos de entradas que segmentarán el intérprete CPython, otorgarán acceso a cualquier clase que desee, y así sucesivamente.

43

eval() permitirá que datos maliciosos pongan en peligro todo el sistema, maten a su gato, coman a su perro y le hagan el amor a su esposa.

Recientemente se produjo un hilo acerca de cómo hacer este tipo de cosas de forma segura en la lista de python-dev, y las conclusiones fueron:

  • Es muy difícil hacer esto correctamente.
  • Requiere parches para que el intérprete de Python bloquee muchas clases de ataques.
  • No lo hagas a menos que realmente quieras.

de inicio aquí para leer sobre el desafío: http://tav.espians.com/a-challenge-to-break-python-security.html

qué situación hace que desea utilizar eval() en? ¿Quieres que un usuario pueda ejecutar expresiones arbitrarias? ¿O quieres transferir datos de alguna manera? Tal vez sea posible bloquear la entrada de alguna manera.

+2

+1: ¿Quién es la persona malintencionada que inserta el código malicioso que está evaluando()? Encuentra a esa persona, en serio. La mayor parte de "eval es inseguro" es hipotético agitar la mano sobre una persona malvada que nadie puede identificar. –

+7

@S. Lott: ¿No es una de las ideas principales detrás de la seguridad * prevenir * que sucedan cosas malas en lugar de esperar que puedas identificar al atacante y convencerlos de que no vuelvan a hacerlo? ¿Por qué desalentar las buenas prácticas? –

+2

Cualquier situación en la que una persona en Internet tenga que escribir código no confiable para ejecutar en sus sistemas requiere que las personas que no son de confianza no puedan atacar. "¿Quién es esta persona", si escribiste algo inseguro con eval() y lo sabía? Sería yo para mostrarte que no deberías haber hecho eso. – Jerub

4

Usted es probablemente mejor de girar en torno a la pregunta:

  1. ¿Qué tipo de expresiones estás queriendo a eval?
  2. ¿Se puede asegurar que solo las cadenas que coincidan con una sintaxis estrechamente definida sean eval() d?
  3. A continuación, considere si que es seguro.

Por ejemplo, si desea permitir que el usuario ingrese una expresión algebraica para su evaluación, considere limitarlos a nombres de variable de una letra, números y un conjunto específico de operadores y funciones. No eval() cadenas que contengan algo más.

+0

O, considere esto: encuentre a la persona que sigue poniendo código malicioso en sus expresiones de evaluación. Eduque a esa persona sobre las consecuencias de su comportamiento antisocial. Seriamente. ¿Quién está poniendo el código en las expresiones de evaluación? –

+3

@ S.Lott - Si está escribiendo programas de criptografía, es Carol o Eve, y para el manejo del correo electrónico es [email protected], pero no sé si alguna vez identificamos quién es en el caso general. – MarkusQ

+0

Iría un paso adelante y preguntaría * por qué * quiere hacer esto en absoluto. –

6

Tenga en cuenta que incluso si pasa diccionarios vacíos a eval(), todavía es posible segfault (C) Python con algunos trucos de sintaxis.Por ejemplo, intente esto en su intérprete: eval("()"*8**5)

+0

¿Puedes publicar un ejemplo de esos trucos? – phihag

+0

Whoa, ¿por qué causó una segfault? – jacob

+1

Desborda la pila del compilador. –

9

Puede obtener os usando las funciones integradas: __import__('os').

Para Python 2.6+, el ast module puede ayudar; en particular, ast.literal_eval, aunque depende exactamente de lo que desea evaluar.

2

Hay un muy bueno article on the un-safety of eval() en el tutorial de Mark Pilgrim Dive into Python.

Citado de este artículo:

Al final, es posible de manera segura evaluar expresiones Python no son de confianza, por alguna definición de “seguro” de que resulta no ser muy útil en reales vida. Está bien si solo está jugando , y está bien si solo le pasa la entrada de confianza. Pero cualquier cosa es solo pedir problema.

+1

El enlace ya no es válido. – GingerPlusPlus

+0

@GingerPlusPlus: gracias, parece que Mark ha movido su dominio. He actualizado los enlaces. –

Cuestiones relacionadas