<p>La función de carga numpy con datos malvados provocará la ejecución del comando</p>

Creado en 16 ene. 2019  ·  32Comentarios  ·  Fuente: numpy/numpy

La función de carga numpy con datos malvados provocará la ejecución del comando, si el ataque comparte datos malvados en Internet,
cuando el usuario lo carga, provocará la ejecución del comando.

Ejemplo de código de reproducción:

import numpy
from numpy import __version__
print __version__
import os
import  pickle
class Test(object):
    def __init__(self):
        self.a = 1

    def __reduce__(self):
        return (os.system,('ls',))
tmpdaa = Test()
with open("a-file.pickle",'wb') as f:
    pickle.dump(tmpdaa,f)
numpy.load('a-file.pickle')

Información de la versión de Numpy / Python:

1.14.6

00 - Bug 15 - Discussion Documentation good first issue

Comentario más útil

Todavía estoy a favor de una advertencia al cargar datos de objetos, puede ser un poco "demasiado tarde", pero hace que la transición sea mucho menos ruidosa. Podríamos agregar una advertencia al guardar (solo una advertencia permanente). Hay un RP abierto que espero que se transforme en algo más parecido. Si desea dedicarle tiempo, generalmente estamos contentos con las relaciones públicas.
En cualquier caso, me parece que se trata de una conversión para comenzar pronto un ciclo de desaprobación, y creo que eso sucederá (pero será antes si alguien lo retoma;)). Puede haber una pequeña posibilidad de que una solicitud se retrase, pero lo dudo y es difícil saberlo sin intentarlo.

Todos 32 comentarios

la versión <= 1.16.0, funcionó

Sí, por eso se agregó np.load(allow_pickle=True) , ahora supongo que podríamos hacer un movimiento para cambiar a False y dar un mensaje bien legible "use allow_pickle="True" si confíe en este archivo ".

Estoy de acuerdo en que este sería el mejor valor predeterminado, por lo que estoy dispuesto a impulsar esa desaprobación, incluso si desafortunadamente es un poco ruidoso, por ejemplo, para todos aquellos científicos que solo comparten algunos datos en el laboratorio (o simplemente guardan / recargan ellos mismos).

Así que allow_pickle se agregó en abril de 2015, por lo que parece que debería haber existido desde numpy 1.10. Así que creo que ese movimiento se vuelve más realista ahora, ya que dudo que muchos que usan / apoyan 1.17 también admitirán 1.10 (eliminando el dolor de apoyar al kwarg o no apoyarlo). Aunque por el momento parece scipy al menos todavía soporta 1.8 en la versión 1.

parece que va a durar mucho tiempo

Sugeriría registrar una advertencia de desaprobación y dar una fecha si desea una transición sin problemas.

@Plazmaz, por supuesto, iría con un VisibleDeprecationWarning, si queremos que los usuarios ocasionales dejen de hacerlo. Luego, desaprobar después de uno o dos lanzamientos. El problema es que es molesto trabajar alrededor si es necesario y el kwarg no existe en algunas versiones anteriores. Porque entonces tienes que hacer if np.__version__ > ...: use kwarg else do not use kwarg para evitar la advertencia y dar soporte a ambos.

De todos modos, creo que hay una buena posibilidad de que lo consigas en 1,17. Entonces, si se siente abierto a un PR, pero es posible que deseemos hacer ping a la lista de correo para ver si alguien se queja.

Hola, mantenedor de Fedora Numpy RPM. ¿Cuál es una buena manera de mitigar esto en el empaquetado de distribución?

No conozco una forma bonita. Dependiendo del nivel de preocupación, estaría dispuesto a agregar una advertencia muy pronto, de modo que definitivamente esté allí en 1.17. Si alguien está extremadamente preocupado, podríamos discutir sobre el backporting o moverse más rápido, pero eso dependería mucho de si el downstream depende de ello.

Estoy trabajando en esto.

cc @jeanqasaur re: experiencia en seguridad / vulnerabilidad

Hola, mantenedor de Fedora Numpy RPM. ¿Cuál es una buena manera de mitigar esto en el empaquetado de distribución?

@limburgher : ¿qué hace fedora con exactamente la misma funcionalidad integrada en Python? No está claro que esto sea algo que deba mitigarse.

Si bien no me opongo a cambiar el valor predeterminado, parece incorrecto declarar esto como una vulnerabilidad. Funciona según lo documentado y diseñado.

Desafortunadamente, la regla es que una vez que se asigna un número CVE, ya no importa si hay algún error o no, las distribuciones deben intentar hacer algo para demostrar a sus clientes que están brindando valor. No estoy seguro de qué sería eso aquí, pero las empresas y el personal de operaciones siempre están luchando para administrar la avalancha de vulnerabilidades en curso, y las herramientas que utilizan para hacerlo no tienen mucho espacio para comunicar matices, así que esa es la forma en que la presión va. Sin embargo, no tenemos clientes, por lo que no necesariamente deberíamos tener eso en cuenta nosotros mismos.

Podemos decir durante save y load si un archivo en particular usa pickle o no, ¿verdad? Probablemente sea bueno migrar a allow_pickle=False en ambos casos, con un período intermedio en el que emitimos algún tipo de advertencia de depreciación exactamente en los casos en los que save o load realmente necesitan para usar pickle y allow_pickle no se especificó.

@ eric-wieser La diferencia con el pickle stdlib es que load / save realidad puede evitar el uso de pickle en la mayoría de los casos (por ejemplo, matrices simples de tipos primitivos); pickle solo se usa en casos más exóticos, como matrices de objetos o IIRC, ciertos tipos de dtipos complicados. Esto hace posible que las personas que utilizan principalmente el caso seguro se pierdan de que existe el caso inseguro, si no leen los documentos con suficiente atención. Y de todos modos, dado que tenemos un "modo seguro" y un "modo inseguro", es mejor que el "modo seguro" sea el predeterminado. Para stdlib pickle OTOH, siempre es 100% inseguro el 100% del tiempo, por lo que no tiene sentido preocuparse por los valores predeterminados.

Honestamente, si es una funcionalidad intencional documentada, puedo cerrar el BZ en buena conciencia, especialmente si la seguridad es la predeterminada. No sé cómo manejamos la funcionalidad de Python. Veré.

De mi examen de la especificación, no creo que cambiemos nada desde el principio en ese sentido.

¿Se ha disputado el CVE? Eso podría aclarar el escenario para los mantenedores.

El CVE parece en gran parte falso. Que numpy.load pueda ejecutar código arbitrario es bien conocido y documentado, y es necesario para cargar matrices de objetos Python serializadas. El usuario puede prohibir la carga de matrices de objetos pasando allow_pickle=False a esta función de biblioteca.

Hubiera sido mejor si el valor predeterminado hubiera sido cargar matrices de objetos solo cuando se le preguntó explícitamente, pero es así por razones históricas. La transición también se ha sugerido antes, y la discusión anterior trata sobre cómo hacerla de una manera que no rompa incontrolablemente la compatibilidad con versiones anteriores.

Sin embargo, el uso descuidado de numpy.load , de manera similar al decapado de Python, puede generar vulnerabilidades en las aplicaciones posteriores.

Que numpy.load pueda ejecutar código arbitrario es bien conocido y documentado, y es necesario para cargar matrices de objetos Python serializadas.

Preferiría solo decir que está documentado. He estado usando numpy durante algunos años, y aunque no soy un usuario frecuente de numpy.save / numpy.load , no me resultaba obvio en absoluto que numpy.load sufre de la misma vulnerabilidad que pickle . Por supuesto, no sabía que numpy.load podría usar pickle debajo del capó (solo uso matrices nativas numpy y nunca lo pensé, exactamente el escenario que mencionó @njsmith ).

El hecho de que pickle es vulnerable es bien conocido, y su documentación tiene una gran advertencia roja en la parte superior que dice

Advertencia : el módulo pickle no es seguro contra datos construidos erróneamente o maliciosamente. Nunca elimine los datos recibidos de una fuente no confiable o no autenticada.

En comparación, los documentos de numpy.load parecen mencionar todo el aspecto de seguridad como un aparte en la descripción de su palabra clave allow_pickle :

allow_pickle: _bool, opcional_
Permitir cargar matrices de objetos en escabeche almacenados en archivos npy. Las razones para no permitir los encurtidos incluyen la seguridad, ya que cargar datos encurtidos puede ejecutar código arbitrario. Si no se permiten los encurtidos, la carga de matrices de objetos fallará. Predeterminado: verdadero

No odiaría si pudiéramos poner una gran advertencia roja en la documentación de numpy.load , al menos hasta que allow_pickle=False convierta en el valor predeterminado. Hasta que se realice ese cambio, ver numpy.load debería generar las mismas banderas rojas en la mente que pickle.load .

Documentación PR bienvenido por numpy.load

La documentación ahora tiene una advertencia sobre pepinillos

Desafortunadamente, la regla es que una vez que se asigna un número CVE, ya no importa si hay algún error o no, las distribuciones tienen que intentar hacer _algo_ para demostrar a sus clientes que están brindando valor. No estoy seguro de qué sería eso aquí, pero las empresas y el personal de operaciones siempre están luchando para administrar la avalancha de vulnerabilidades en curso, y las herramientas que utilizan para hacerlo no tienen mucho espacio para comunicar matices, así que esa es la forma en que la presión va.

@njsmith no es tan malo : haremos numpy.load predeterminado a allow_pickle a False , que en realidad no es una idea completamente estúpida.

El único riesgo que veo con eso es que cualquier proyecto que no establezca explícitamente allow_pickle se romperá.

No solo debemos preocuparnos por los proyectos de los usuarios finales; me preocupan las bibliotecas posteriores que proporcionan mylib.load que envuelven np.load . Estos comenzarán a fallar al cargar matrices de objetos. Con ellos pasará una de tres cosas:

  • Permanecen abandonados y nunca funcionarán en matrices de objetos de la forma en que solían hacerlo. Los usuarios encontrarán que sus datos son rehenes y tendrán que degradar Numpy para recuperarlos.
  • Vuelven a publicar la configuración allow_pickle=True para reanudar el comportamiento anterior, que son las bibliotecas posteriores que indican que creen que este no es un vector de ataque que les importa. Esto todavía les cuesta un lanzamiento incompatible
  • Expondrán allow_pickle=False en su propia API, empujando el problema hacia abajo.

Mi preferencia seria:

  • No haga nada para np.save . Tener un error de secuencia de comandos de larga duración al final al guardar una matriz de objetos es una experiencia terrible.
  • Cambie el valor predeterminado en np.load a None . Detecta al usuario que no pasa True o False explícitamente y emita un UserWarning explicando los peligros, pidiéndole que elija entre seguridad ( False ) y objeto soporte de matriz ( True ). Por defecto al status quo después de emitir esta advertencia. Tengo entendido que el problema aquí es la falta de conciencia. Ninguna de las opciones es correcta en todos los casos, por lo que no creo que debamos cambiar repentinamente de opinión sobre el valor predeterminado sin previo aviso.

@ eric-wieser buen punto sobre el dolor de un script que se bloquea. Estaría dispuesto a dar UserWarning por defecto.

La pregunta es qué queremos hacer a largo plazo en load . No estoy seguro de que me guste obligar a todos a usar el kwarg (para silenciar la advertencia), cuando la matriz es segura. Aunque tiene el mérito de que no hay peligro de bloquear a alguien de sus datos ... OTOH, si la advertencia solo aparece en una carga "insegura", puede que sea demasiado tarde. En este momento creo que tengo una ligera preferencia por hacer que el período de transición sea un poco más largo.

OTOH, si la advertencia solo aparece en una carga "insegura", puede que sea demasiado tarde.

Ya sea:

  • La biblioteca / script ya existe y está publicado; cualquier cosa que hagamos ya es demasiado tarde
  • La biblioteca / script aún se está desarrollando. El desarrollador debería ver la advertencia durante las pruebas locales en un archivo seguro y debería poder tomar una decisión informada sobre el comportamiento que desea. Por esta razón, debemos emitir la advertencia incluso si la matriz es segura (y probablemente antes de cargarla, en caso de que tengan el equivalente en Python de -Werror set).

Sí, definitivamente estoy de acuerdo con las bibliotecas, pero creo que puede ser un poco molesto por la gran cantidad de scripts más cortos.

Cambie el valor predeterminado en np.load a None . Detecte al usuario que no pasa True o False explícitamente, y emita un UserWarning explicando los peligros, pidiéndole que elija entre seguridad ( False ) y objeto soporte de matriz ( True ). Por defecto al status quo después de emitir esta advertencia. Tengo entendido que el problema aquí es la falta de conciencia. Ninguna de las opciones es correcta en todos los casos, por lo que no creo que debamos cambiar repentinamente de opinión sobre el valor predeterminado sin previo aviso.

Sin embargo, esto suena muy molesto. La mayoría de las personas (creo) no guardan / cargan matrices de objetos. Y el peor de los casos si alguien pasa por alto la advertencia es (eventualmente) que su script se bloquee al cargar, los datos aún están seguros en el disco y vuelven a intentarlo con la bandera allow_pickle .

¿Está más allá de la responsabilidad de numpy intentar cargar de forma segura primero y solo gritar en caso de que falle debido a las matrices de objetos? Eso eliminaría el trabajo adicional para la mayoría de los casos de uso (no objetivos), pero supongo que también reduciría la visibilidad de todo el problema de seguridad. Por otra parte, creo que "los usuarios deben ser muy conscientes" y "los usuarios no deben ser molestados" son esfuerzos un poco contradictorios aquí.

* Change the default in `np.load` to `None`. Detect the user not passing in `True` or `False` explicitly, and emit a `UserWarning` explaining the dangers, asking them to choose between security (`False`) and object array support (`True`). Default to the status quo after emitting this warning. It's my understanding that the problem here is lack of awareness. Neither choice is correct in all cases, so I don't think we should suddenly change our minds about the default without warning.

¿Y este parche ?

* Change the default in `np.load` to `None`. Detect the user not passing in `True` or `False` explicitly, and emit a `UserWarning` explaining the dangers, asking them to choose between security (`False`) and object array support (`True`). Default to the status quo after emitting this warning. It's my understanding that the problem here is lack of awareness. Neither choice is correct in all cases, so I don't think we should suddenly change our minds about the default without warning.

¿Qué pasa con este parche?

--- a/numpy/lib/npyio.py
+++ b/numpy/lib/npyio.py
@@ -265,7 +265,7 @@ class NpzFile(object):
         return self.files.__contains__(key)


-def load(file, mmap_mode=None, allow_pickle=True, fix_imports=True,
+def load(file, mmap_mode=None, allow_pickle=None, fix_imports=True,
          encoding='ASCII'):
     """
     Load arrays or pickled objects from ``.npy``, ``.npz`` or pickled files.
@@ -367,6 +367,16 @@ def load(file, mmap_mode=None, allow_pic
     memmap([4, 5, 6])

     """
+
+    if allow_pickle is None:
+        UserWarning("""
+        numpy.load() run without explicit setting allow_pickle option.
+        If you are not completely certain about security of the pickled
+        data, you are strongly encouraged to set allow_pickle to False,
+        otherwise you can set it to True.
+        """)
+        allow_pickle = False
+
     own_fid = False
     if isinstance(file, basestring):
         fid = open(file, "rb")

Todavía estoy a favor de una advertencia al cargar datos de objetos, puede ser un poco "demasiado tarde", pero hace que la transición sea mucho menos ruidosa. Podríamos agregar una advertencia al guardar (solo una advertencia permanente). Hay un RP abierto que espero que se transforme en algo más parecido. Si desea dedicarle tiempo, generalmente estamos contentos con las relaciones públicas.
En cualquier caso, me parece que se trata de una conversión para comenzar pronto un ciclo de desaprobación, y creo que eso sucederá (pero será antes si alguien lo retoma;)). Puede haber una pequeña posibilidad de que una solicitud se retrase, pero lo dudo y es difícil saberlo sin intentarlo.

¿Podría cerrar este problema, ya que se menciona en https://nvd.nist.gov/vuln/detail/CVE-2019-6446 debido a que nexus iq todavía considera que tiene Vulnerable?

gracias @ Manjunath07

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

kevinzhai80 picture kevinzhai80  ·  4Comentarios

Kreol64 picture Kreol64  ·  3Comentarios

dcsaba89 picture dcsaba89  ·  3Comentarios

Levstyle picture Levstyle  ·  3Comentarios

astrofrog picture astrofrog  ·  4Comentarios