<p>La fonction de chargement numpy avec des données maléfiques provoquera l'exécution de la commande</p>

Créé le 16 janv. 2019  ·  32Commentaires  ·  Source: numpy/numpy

La fonction de chargement numpy avec des données malveillantes provoquera l'exécution de la commande, si l'attaque partage des données malveillantes sur Internet,
lorsque l'utilisateur le charge, cela provoquera l'exécution de la commande.

Exemple de code de reproduction:

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')

Informations sur la version Numpy / Python:

1.14.6

00 - Bug 15 - Discussion Documentation good first issue

Commentaire le plus utile

Je suis toujours en faveur d'un avertissement lors du chargement de données d'objets, cela peut être un peu "trop ​​tard", mais cela rend la transition beaucoup moins bruyante. Nous pourrions ajouter un avertissement lors de l'enregistrement (juste un avertissement permanent). Il y a un PR ouvert que j'espère transformer en quelque chose de plus comme ça. Si vous souhaitez y consacrer du temps, nous sommes généralement satisfaits des RP.
Il me semble que c'est une conversion vers le démarrage d'un cycle de dépréciation bientôt dans tous les cas, et je pense que cela se produira (mais ce sera plus tôt si quelqu'un le prend;)). Il y a peut-être une petite chance qu'une demande soit retardée, mais j'en doute, et il est difficile de savoir sans essayer.

Tous les 32 commentaires

la version <= 1.16.0, a fonctionné

Oui, c'est pourquoi np.load(allow_pickle=True) été ajouté, maintenant je suppose que nous pourrions passer à la valeur par défaut de False et donner un message bien lisible "utilisez allow_pickle="True" si vous faites confiance à ce fichier ".

Je suis d'accord que ce serait la meilleure valeur par défaut, donc je suis ouvert à pousser cette dépréciation, même si c'est malheureusement un peu bruyant, par exemple pour tous ces scientifiques partageant simplement des données dans le laboratoire (ou simplement en sauvegardant / rechargeant eux-mêmes).

Donc allow_pickle été ajouté en avril 2015, il semblerait donc que cela aurait dû exister depuis numpy 1.10. Je pense donc que ce mouvement devient plus réaliste maintenant, car je doute que beaucoup utilisant / supportant la version 1.17 supportent également la version 1.10 (en supprimant la douleur de supporter le kwarg ou de ne pas le supporter). Bien que pour le moment, il semble que scipy au moins supporte toujours 1.8 dans la version 1.

il semble que ça durera longtemps

Je suggérerais de consigner un avertissement de désapprobation et de donner une date si vous voulez une transition en douceur.

@Plazmaz bien sûr, j'irais avec un VisibleDeprecationWarning, si nous voulons que les utilisateurs occasionnels arrêtent de le faire. Puis obsolète après une ou deux versions. Le fait est qu'il est ennuyeux de contourner le problème si vous le devez et le kwarg n'existe pas dans certaines versions plus anciennes. Parce qu'alors, vous devez faire if np.__version__ > ...: use kwarg else do not use kwarg pour éviter l'avertissement et prendre en charge les deux.

Quoi qu'il en soit, je pense qu'il y a de bonnes chances que vous puissiez le mettre en 1.17. Donc, si vous vous sentez ouvert, un PR, mais nous voudrons peut-être envoyer un ping à la liste de diffusion pour voir si quelqu'un se plaint.

Salut, mainteneur de Fedora numpy RPM. Quel est un bon moyen d'atténuer cela dans le packaging de la distribution?

Je ne connais pas de belle manière. Selon le niveau de préoccupation, je serais prêt à ajouter un avertissement très prochainement, pour qu'il soit définitivement là en 1.17. Si quelqu'un est extrêmement préoccupé, nous pourrions discuter de son rétroportage ou d'aller plus vite, mais cela dépendrait beaucoup du fait que l'aval en dépend ou non.

Je travaille là- dessus.

cc @jeanqasaur re: expertise sécurité / vulnérabilité

Salut, mainteneur de Fedora numpy RPM. Quel est un bon moyen d'atténuer cela dans le packaging de la distribution?

@limburgher : que fait fedora à propos de la même fonctionnalité intégrée à Python? Il n'est pas certain que ce soit quelque chose à atténuer.

Bien que je ne sois pas opposé à la modification de la valeur par défaut, il semble incorrect de déclarer cela comme une vulnérabilité. Cela fonctionne comme documenté et conçu.

Malheureusement, la règle est qu'une fois qu'un numéro CVE est attribué, peu importe qu'il y ait un bogue ou non, les distributions doivent essayer de faire quelque chose pour prouver à leurs clients qu'elles fournissent de la valeur. Je ne sais pas ce que cela serait ici, mais les entreprises et les opérateurs ont toujours du mal à gérer le flot continu de vulnérabilités, et les outils qu'ils utilisent pour le faire n'ont pas beaucoup de place pour communiquer les nuances, c'est donc la façon dont la pression va. Cependant, nous n'avons pas de clients, nous ne devons donc pas nécessairement en tenir compte.

Nous pouvons dire pendant save et load si un fichier particulier utilise pickle ou non, non? Il est probablement bon de migrer vers allow_pickle=False dans les deux cas, avec une période intermédiaire où nous émettons une sorte d'avertissement de dépréciation exactement dans les cas où save ou load réellement besoin d'utiliser pickle et allow_pickle n'a pas été spécifié.

@ eric-wieser La différence avec le pickle stdlib est que load / save peut en fait éviter d'utiliser pickle dans la plupart des cas (par exemple, des tableaux simples de types primitifs); pickle n'est utilisé que dans des cas plus exotiques comme les tableaux d'objets ou certains types de dtypes compliqués de l'IIRC. Cela permet aux personnes qui utilisent principalement le cas sûr de manquer que le cas dangereux existe, s'ils ne lisent pas les documents assez attentivement. Et de toute façon, étant donné que nous avons à la fois un "mode sans échec" et un "mode non sécurisé", il est préférable que le "mode sans échec" soit la valeur par défaut. Pour stdlib pickle OTOH, il est toujours 100% dangereux à 100% du temps, il n'y a donc pas lieu de s'inquiéter des valeurs par défaut.

Honnêtement, s'il s'agit d'une fonctionnalité intentionnelle documentée, je peux fermer le BZ en toute bonne conscience, surtout si la sécurité est la valeur par défaut. Je ne sais pas comment nous gérons les fonctionnalités de Python. Je vais regarder.

D'après mon examen des spécifications, je ne pense pas que nous modifions quoi que ce soit de l'amont à cet égard.

La CVE a-t-elle été contestée? Cela pourrait rendre le scénario plus clair pour les responsables.

Le CVE semble en grande partie faux. Que numpy.load puisse exécuter du code arbitraire est bien connu et documenté, et il est nécessaire pour charger des tableaux d'objets Python sérialisés. L'utilisateur peut interdire le chargement de tableaux d'objets en passant allow_pickle=False à cette fonction de bibliothèque.

Il aurait été préférable que la valeur par défaut ait été de charger les tableaux d'objets uniquement lorsque cela est explicitement demandé, mais c'est comme ça pour des raisons historiques. La transition a également été suggérée auparavant, et la discussion ci-dessus porte sur la manière de la réaliser d'une manière qui ne rompt pas de manière incontrôlable la compatibilité descendante.

Une utilisation imprudente de numpy.load , de la même manière que le pickling Python, peut cependant conduire à des vulnérabilités dans les applications en aval.

Que numpy.load puisse exécuter du code arbitraire est bien connu et documenté, et il est nécessaire pour charger des tableaux d'objets Python sérialisés.

Je dirais plutôt que c'est documenté. J'utilise numpy depuis quelques années, et même si je ne suis pas un utilisateur fréquent de numpy.save / numpy.load ce n'était pas du tout évident pour moi que numpy.load souffre de la même vulnérabilité que pickle . Bien sûr, je ne savais pas que numpy.load pourrait utiliser pickle sous le capot (je n'utilise que des tableaux numpy-natifs et je n'y ai jamais pensé, exactement le scénario mentionné par @njsmith ).

Le fait que pickle soit vulnérable est bien connu, et sa documentation a un gros avertissement rouge en haut indiquant

Attention : le module pickle n'est pas sécurisé contre les données erronées ou construites de manière malveillante. Ne supprimez jamais les données reçues d'une source non approuvée ou non authentifiée.

En comparaison, la documentation de numpy.load semble mentionner tout l'aspect sécurité en aparté dans la description de son mot -

allow_pickle: _bool, facultatif_
Autorise le chargement de tableaux d'objets décapés stockés dans des fichiers npy. Les raisons pour interdire les pickles incluent la sécurité, car le chargement de données pickles peut exécuter du code arbitraire. Si les pickles ne sont pas autorisés, le chargement des tableaux d'objets échouera. Par défaut: vrai

Je ne détesterais pas si nous pouvions mettre un Big Red Warning dans la documentation de numpy.load , au moins jusqu'à ce que allow_pickle=False devienne la valeur par défaut. Jusqu'à ce que ce changement soit fait, voir numpy.load devrait soulever les mêmes drapeaux rouges dans l'esprit que pickle.load lève.

Documentation PR bienvenue pour numpy.load

La documentation a maintenant un avertissement concernant le cornichon

Malheureusement, la règle est qu'une fois qu'un numéro CVE est attribué, peu importe qu'il y ait un bogue ou non, les distributions doivent essayer de faire _quelque chose_ pour prouver à leurs clients qu'elles fournissent de la valeur. Je ne sais pas ce que cela serait ici, mais les entreprises et les opérateurs ont toujours du mal à gérer le flot continu de vulnérabilités, et les outils qu'ils utilisent pour le faire n'ont pas beaucoup de place pour communiquer les nuances, c'est donc la façon dont la pression va.

@njsmith ce n'est pas si mal : nous allons faire de numpy.load par défaut de allow_pickle à False , ce qui n'est en fait pas une idée complètement stupide.

Le seul risque que je vois avec cela est que tout projet qui ne définit pas explicitement allow_pickle se cassera.

Ce ne sont pas seulement les projets des utilisateurs finaux dont nous devons nous soucier - je m'inquiète des bibliothèques en aval fournissant mylib.load qui encapsule np.load . Ceux-ci commenceront à ne pas charger les tableaux d'objets. Une des trois choses se produira avec eux:

  • Ils restent abandonnés et ne fonctionneront jamais sur des tableaux d'objets comme ils le faisaient auparavant. Les utilisateurs trouveront que leurs données sont retenues en otage et devront rétrograder numpy pour les récupérer.
  • Ils re-libèrent le paramètre allow_pickle=True pour reprendre l'ancien comportement - qui est les bibliothèques en aval indiquant qu'ils pensent que ce n'est pas un vecteur d'attaque qui leur tient à cœur. Cela leur coûte toujours une version incompatible
  • Ils exposeront allow_pickle=False dans leur propre API, poussant le problème en aval.

Ma préférence serait:

  • Ne rien faire pour np.save . Avoir un crash de script de longue durée à la fin lors de l'enregistrement d'un tableau d'objets est une expérience horrible.
  • Remplacez la valeur par défaut de np.load par None . Détectez l'utilisateur qui ne passe pas explicitement True ou False et émettez un UserWarning expliquant les dangers, en leur demandant de choisir entre la sécurité ( False ) et l'objet prise en charge des tableaux ( True ). Par défaut sur le statu quo après avoir émis cet avertissement. Je crois comprendre que le problème ici est le manque de sensibilisation. Aucun des deux choix n'est correct dans tous les cas, donc je ne pense pas que nous devrions soudainement changer d'avis sur la valeur par défaut sans avertissement.

@ eric-wieser bon point sur la douleur d'un script qui plante. Je serais partant pour donner un UserWarning par défaut.

La question est de savoir ce que nous voulons faire à long terme en load . Je ne suis pas sûr que j'aime forcer tout le monde à utiliser le kwarg (pour faire taire l'avertissement), lorsque le tableau est en sécurité. Bien qu'il n'ait le mérite de ne pas risquer de verrouiller quelqu'un hors de ses données ... OTOH, si l'avertissement n'apparaît que sur une charge "non sécurisée", il peut être trop tard. À l'heure actuelle, je pense avoir une légère préférence pour allonger un peu la période de transition.

OTOH, si l'avertissement n'apparaît que sur une charge "non sûre", il est peut-être trop tard.

Soit:

  • La bibliothèque / script existe déjà et est publié - tout ce que nous faisons est déjà trop tard
  • La bibliothèque / script est toujours en cours de développement. Le développeur doit voir l'avertissement lors des tests locaux sur un fichier sécurisé et doit être en mesure de prendre une décision éclairée sur le comportement souhaité. Pour cette raison, nous devrions émettre l'avertissement même si le tableau est sûr (et probablement avant de le charger, juste au cas où ils auraient l'équivalent python de -Werror set).

Oui, je suis tout à fait d'accord pour les bibliothèques, mais je pense que cela peut être un peu ennuyeux pour le grand nombre de scripts plus courts.

Remplacez la valeur par défaut de np.load par None . Détectez l'utilisateur ne passant pas explicitement True ou False , et émettez un UserWarning expliquant les dangers, en leur demandant de choisir entre la sécurité ( False ) et l'objet prise en charge des tableaux ( True ). Par défaut sur le statu quo après avoir émis cet avertissement. Je crois comprendre que le problème ici est le manque de sensibilisation. Aucun des deux choix n'est correct dans tous les cas, donc je ne pense pas que nous devrions soudainement changer d'avis sur la valeur par défaut sans avertissement.

Cela semble super ennuyeux cependant. La plupart des gens (je crois) ne sauvegardent / ne chargent pas de tableaux d'objets. Et le pire des cas si quelqu'un manque l'avertissement est (éventuellement) que son script plante lors du chargement, les données sont toujours en sécurité sur le disque, et ils réessayent avec l'indicateur allow_pickle .

Est-il au-delà de la responsabilité de numpy d'essayer d'abord de charger en toute sécurité et de ne crier qu'en cas d'échec en raison de tableaux d'objets? Cela supprimerait du travail supplémentaire pour la plupart des cas d'utilisation (non objectifs), mais je suppose que cela réduirait également la visibilité de l'ensemble du problème de sécurité. Là encore, je pense que «les utilisateurs doivent être très conscients» et «les utilisateurs ne doivent pas être incommodés» sont des efforts un peu contradictoires ici.

* 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.

Et ce patch ?

* 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'en est-il de ce patch:

--- 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")

Je suis toujours en faveur d'un avertissement lors du chargement de données d'objets, cela peut être un peu "trop ​​tard", mais cela rend la transition beaucoup moins bruyante. Nous pourrions ajouter un avertissement lors de l'enregistrement (juste un avertissement permanent). Il y a un PR ouvert que j'espère transformer en quelque chose de plus comme ça. Si vous souhaitez y consacrer du temps, nous sommes généralement satisfaits des RP.
Il me semble que c'est une conversion vers le démarrage d'un cycle de dépréciation bientôt dans tous les cas, et je pense que cela se produira (mais ce sera plus tôt si quelqu'un le prend;)). Il y a peut-être une petite chance qu'une demande soit retardée, mais j'en doute, et il est difficile de savoir sans essayer.

Pourriez-vous s'il vous plaît fermer ce problème car il est référencé dans https://nvd.nist.gov/vuln/detail/CVE-2019-6446 à cause duquel nexus iq considère toujours qu'il est vulnérable

merci @ Manjunath07

Cette page vous a été utile?
0 / 5 - 0 notes