Python: ¿puedo descomprimir con seguridad los datos que no son de confianza?

La documentación del módulo pickle dice al principio:

Advertencia : el módulo pickle no está diseñado para ser seguro contra datos erróneos o creados de manera malintencionada. Nunca descomprima los datos recibidos de una fuente no confiable o no autenticada.

Sin embargo, más abajo, bajo restricciones globales , parece describir una manera de hacer que la eliminación de datos sea segura utilizando una lista blanca de objetos permitidos.

¿Esto significa que puedo desmarcar de forma segura los datos que no son de confianza si utilizo un RestrictedUnpickler que permite solo algunos tipos “elementales” o hay problemas de seguridad adicionales que no se tratan con este método? Si los hay, ¿hay alguna otra manera de hacer que la eliminación sea segura (obviamente, a costa de no poder eliminar todas las transmisiones)?

Con “tipos elementales” me refiero precisamente a lo siguiente:

  • bool
  • str , bytes , bytearray
  • int , float , complex
  • tuple , list , dict , set y frozenset

Me atrevería a decir que no existe una forma segura de utilizar pickle para manejar datos no confiables.

Incluso con los globales restringidos, la naturaleza dinámica de Python es tal que un pirata informático determinado todavía tiene la posibilidad de encontrar una forma de regresar al mapeo de __builtins__ y de allí a las Joyas de la Corona.

Consulte las publicaciones del blog de Ned Batchelder sobre eludir las restricciones en eval() que se aplican en igual medida a pickle .

Recuerde que pickle sigue siendo un lenguaje de stack y no puede prever todos los objetos posibles producidos al permitir llamadas arbitrarias, incluso a un conjunto limitado de globales. La documentación de pickle tampoco menciona los copyreg EXT* que permiten llamar a extensiones copyreg ; Tendrá que dar cuenta de cualquier cosa instalada en ese registro también aquí. Todo lo que necesita es un vector que permita que una llamada a un objeto se convierta en un equivalente de getattr para que sus defensas se desmoronen.

Como mínimo, utilice una firma criptográfica para sus datos para que pueda validar la integridad. Limitará los riesgos, pero si un atacante alguna vez lograba robar sus secretos de firma (claves), podría volver a pasarle un pepinillo.

En su lugar, usaría un formato inocuo existente como JSON y agregaría anotaciones de tipo; por ejemplo, almacenar datos en diccionarios con una clave de tipo y convertir al cargar los datos.

Esta idea se ha discutido también en la lista de correo python-ideas cuando se aborda el problema de agregar una alternativa segura en la biblioteca estándar. Por ejemplo aquí :

Para hacerlo más seguro, tendría un desalojador restringido como predeterminado (para carga / carga) y obligaría a las personas a anularlo si desean aflojar las restricciones. Para ser realmente explícito, haría que las cargas / cargas solo funcionen con los tipos incorporados.

Y también aquí :

Siempre he querido una versión de pickle.loads () que tome una lista de clases que se pueden crear instancias.

¿Es suficiente para usted lo siguiente: http://docs.python.org/3.4/library/pickle.html#restricting-globals ?

De hecho, es. ¡Gracias por mencionarlo! Nunca he pasado la parte de la interfaz del módulo de los documentos. Tal vez la advertencia en la parte superior de la página también podría mencionar que hay formas de mitigar los problemas de seguridad y apuntar a # restricciones-globales.

Sí, sería una buena idea 🙂

Por lo tanto, no sé por qué no se ha cambiado la documentación, pero de acuerdo con mí, usar una RestrictedUnpickler para restringir los tipos que se pueden descifrar es una solución segura. Por supuesto, podría haber errores en la biblioteca que comprometan el sistema, pero también podría haber un error en OpenSSL que muestre datos de memoria aleatorios a todos los que lo soliciten.