Una función f()
usa eval()
(o algo tan peligroso) con los datos que creé y almacené en local_file
la máquina que ejecuta mi programa:
import local_file
def f(str_to_eval):
# code....
# ....
eval(str_to_eval)
# ....
# ....
return None
a = f(local_file.some_str)
f()
es seguro de ejecutar ya que las cadenas que le proporciono son mías.
Sin embargo, si alguna vez decido usarlo para algo inseguro (por ejemplo, entrada del usuario), las cosas podrían salir terriblemente mal . Además, si local_file
deja de ser local, crearía una vulnerabilidad, ya que también necesitaría confiar en la máquina que proporciona ese archivo.
¿Cómo debo asegurarme de nunca "olvidar" que esta función no es segura de usar (a menos que se cumplan criterios específicos)?
Nota: eval()
es peligroso y generalmente puede ser reemplazado por algo seguro.
python
vulnerabilities
Paradoja de Fermi
fuente
fuente
Respuestas:
Defina un tipo para decorar entradas "seguras". En su función
f()
, afirme que el argumento tiene este tipo o arroje un error. Sé lo suficientemente inteligente como para nunca definir un atajodef g(x): return f(SafeInput(x))
.Ejemplo:
Si bien esto puede evitarse fácilmente, hace que sea más difícil hacerlo por accidente. La gente podría criticar una verificación de tipo tan draconiana, pero se perderían el punto. Dado que el
SafeInput
tipo es solo un tipo de datos y no una clase orientada a objetos que podría subclasificarse, verificar la identidad del tipotype(x) is SafeInput
es más seguro que verificar la compatibilidad del tipoisinstance(x, SafeInput)
. Dado que queremos imponer un tipo específico, ignorar el tipo explícito y simplemente hacer un tipeo de pato implícito tampoco es satisfactorio aquí. Python tiene un sistema de tipos, ¡así que usémoslo para detectar posibles errores!fuente
assert
se elimina automáticamente ya que utilizaré el código optimizado de Python. Algo asíif ... : raise NotSafeInputError
sería necesario.eval()
un métodoSafeInput
, para que no necesite una verificación de tipo explícita. Déle al método un nombre que no se use en ninguna de sus otras clases. De esa manera, todavía puedes burlarte de todo para propósitos de prueba.eval
tiene acceso a las variables locales, es posible que el código dependa de cómo muta las variables. Al mover la evaluación a otro método, ya no tendrá la capacidad de mutar variables locales.SafeInput
constructor tome un nombre / identificador del archivo local y haga la lectura misma, asegurando que los datos realmente provengan de un archivo local.Como Joel señaló una vez, haga que el código incorrecto parezca incorrecto (desplácese hacia abajo hasta la sección "La solución real", o mejor aún, léalo por completo; vale la pena, incluso si se trata de nombres de variables en lugar de funciones). Así que humildemente sugiero cambiar el nombre de su función a algo como
f_unsafe_for_external_use()
: lo más probable es que tenga un esquema de abreviatura usted mismo.Editar: creo que la sugerencia de amon es una muy buena variación basada en OO sobre el mismo tema :-)
fuente
Complementando la sugerencia de @amon, también puede pensar en combinar el patrón de estrategia aquí, así como el patrón de objeto del método.
Y luego una implementación 'normal'
Y una implementación admin-input-eval
(Nota: con un ejemplo del mundo real, podría dar un mejor ejemplo).
fuente