tag:blogger.com,1999:blog-9947347.post7416880469098306923..comments2023-07-03T07:37:12.436-03:00Comments on Alejandro Santos: Ejecutando código Python de forma segura con eval()alejolphttp://www.blogger.com/profile/14949586999780473522noreply@blogger.comBlogger7125tag:blogger.com,1999:blog-9947347.post-37470275473220978712015-10-14T07:34:23.647-03:002015-10-14T07:34:23.647-03:00Cierto...
¿qué tal esta versión mejorada?, tira ...Cierto... <br /><br />¿qué tal esta versión mejorada?, tira todas las expresiones que contengan palabras reservadas que no formen parte de las expresiones legales. <br /><br />def eval_wrapper(expression):<br /> PYTHON_RESERVED_WORDS = ('and', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except',<br /> 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or',<br /> 'pass', 'print', 'raise', 'return', 'try', 'while')<br /><br /> EXCEPTION_PYTHON_WORDS = ('index',)<br /><br /> if not type(expression) is str:<br /> raise ValueError('The expression should be a str object')<br /><br /><br /> forbidden_words = [reserved_word for reserved_word in PYTHON_RESERVED_WORDS if reserved_word in expression ]<br /> for fw in forbidden_words:<br /> for exw in EXCEPTION_PYTHON_WORDS:<br /> if not fw in exw:<br /> raise PermissionError('You cannot execute the sentence: {0}'.format(expression))<br /><br /> return eval(expression)Manuel Antonio Castro Pérezhttps://www.blogger.com/profile/06766142684430023882noreply@blogger.comtag:blogger.com,1999:blog-9947347.post-69206468660604388942015-10-14T06:48:53.536-03:002015-10-14T06:48:53.536-03:00Pero ahora con poner "index" en cualquie...Pero ahora con poner "index" en cualquier lugar del string podés conseguir evitar que se evite la validación.<br /><br />>>> eval_wrapper("__import__('modulomaligno') # index")<br />alejolphttps://www.blogger.com/profile/14949586999780473522noreply@blogger.comtag:blogger.com,1999:blog-9947347.post-22274759501701664252015-10-14T06:40:43.529-03:002015-10-14T06:40:43.529-03:00Ah ahora entiendo. Sí es cierto lo sé y soy consci...Ah ahora entiendo. Sí es cierto lo sé y soy consciente. La idea de dicho wrapper es tener muy claro qué vas a permitir y qué no. Desde luego en temas de seguridad no hay una receta mágica que funcione siempre. A mi me funciona porque lo único que necesito es ejecutar <br /><br /><b> obj_list = eval('model_class.objects.filter(' + field_id + '=' + value_field_id + ')')</b><br /><br />Lo que quería decir es que mi eval_wrapper es tremendamente restrictivo. Pero lo que quería mostrar es que para cada aplicación construir un eval restrictivo e ir añadiendo excepciones a esas restricciones. Por ejemplo: <br /><br />def eval_wrapper(expression):<br /> PYTHON_RESERVED_WORDS = ('and', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except',<br /> 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or',<br /> 'pass', 'print', 'raise', 'return', 'try', 'while')<br /><br /> EXCEPTION_PYTHON_WORDS = ('index',)<br /><br /><br /> if not type(expression) is str:<br /> raise ValueError('The expression should be a str object')<br /> for reserved_word in PYTHON_RESERVED_WORDS:<br /> if reserved_word in expression:<br /> for excep_word in EXCEPTION_PYTHON_WORDS:<br /> if excep_word not in expression:<br /> raise PermissionError('You cannot execute the sentence: {0}'.format(expression))<br /><br /> return eval(expression)<br /><br /><br />Eso sí, SIEMPRE SERÁ RESPONSABILIDAD DEL PROGRAMADOR. <br />En fin gracias por tus comentarios y por tu saber. <br /> Manuel Antonio Castro Pérezhttps://www.blogger.com/profile/06766142684430023882noreply@blogger.comtag:blogger.com,1999:blog-9947347.post-51163860755545657542015-10-14T05:56:46.085-03:002015-10-14T05:56:46.085-03:00El siguiente programa es perfectamente valido en P...El siguiente programa es perfectamente valido en Python, devuelve el indice de la letra "a" en el string "hola":<br /><br />>>> 'hola'.index('a')<br />3<br /><br />Usando eval() con este mismo programa devuelve el resultado deseado:<br /><br />>>> eval("'hola'.index('a')")<br />3<br /><br />Sin embargo con tu versión de eval_wrapper no funciona:<br /><br />>>> eval_wrapper("'hola'.index('a')")<br />Traceback (most recent call last):<br /> File "", line 1, in <br /> File "", line 7, in eval_wrapper<br />__main__.PermissionError: You cannot execute the sentence: 'hola'.index('a')<br /><br />La razón es muy simple: al filtrar por keywords inválidas de Python se está tomando la keyword "in" y buscándola como un substring en el codigo a hacer eval, que es un substring de "index".<br />alejolphttps://www.blogger.com/profile/14949586999780473522noreply@blogger.comtag:blogger.com,1999:blog-9947347.post-22520608121799642532015-10-14T05:47:53.992-03:002015-10-14T05:47:53.992-03:00No entiendo tu ejemplo. ¿Podrías explicarme un poc...No entiendo tu ejemplo. ¿Podrías explicarme un poco más por qué no funciona lo que yo he puesto? Aparte de eso, digo que mi eval_wrapper funciona porque lo que quiero hacer es bastante limitado (como limitado debería ser el mismo uso de eval). Lo único que quería hacer notar es que no hay forma de saltarse nada en mi función para usar cosas por detrás. <br />Manuel Antonio Castro Pérezhttps://www.blogger.com/profile/06766142684430023882noreply@blogger.comtag:blogger.com,1999:blog-9947347.post-48372587671905438992015-10-14T04:58:03.934-03:002015-10-14T04:58:03.934-03:00Nuser, tu solucion no funciona en general, estás f...Nuser, tu solucion no funciona en general, estás filtrando casos de uso perfectamente validos, por ejemplo en un str:<br /><br />>>> [x for x in dir("") if any([(y in x) for y in PYTHON_RESERVED_WORDS])]<br />['__class__', '__contains__', '__delattr__', '__format__', '__init__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'rfind', 'rindex', 'splitlines']<br /><br />>>> eval_wrapper("'hola'.index('a')")<br /><br />alejolphttps://www.blogger.com/profile/14949586999780473522noreply@blogger.comtag:blogger.com,1999:blog-9947347.post-87605442234143407792015-10-14T04:32:07.253-03:002015-10-14T04:32:07.253-03:00Hola Alejandro, muy bueno tu artículo sobre la seg...Hola Alejandro, muy bueno tu artículo sobre la seguridad de eval, pero con esta función permito ejecutar el código que yo deseo dentro de una determinada aplicación. <br />Es cierto que es un Eval limitado, pero funcionaría para la invocación de objetos que yo deseo y no deja que se ejecute nada de los ejemplos que ahí tienes. <br /><br />def eval_wrapper(expression):<br /> PYTHON_RESERVED_WORDS = ('and', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except',<br /> 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or',<br /> 'pass', 'print', 'raise', 'return', 'try', 'while')<br /><br /> <br /> if not type(expression) is str:<br /> raise ValueError('The expression should be a str object')<br /> for reserved_word in PYTHON_RESERVED_WORDS:<br /> if reserved_word in expression:<br /> raise PermissionError('You cannot execute the sentence: {0}'.format(expression))<br /><br /> return eval(expression)Manuel Antonio Castro Pérezhttps://www.blogger.com/profile/06766142684430023882noreply@blogger.com