<p>具有邪恶数据的numpy加载函数将导致命令执行</p>

创建于 2019-01-16  ·  32评论  ·  资料来源: numpy/numpy

带有邪恶数据的numpy加载函数将导致命令执行,如果攻击在互联网上共享邪恶数据,
用户加载时,将导致命令执行。

再现代码示例:

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

Numpy / Python版本信息:

1.14.6

00 - Bug 15 - Discussion Documentation good first issue

最有用的评论

我仍然赞成在加载对象数据时发出警告,这可能有点“为时已晚”,但可以减少很多嘈杂的过渡。 保存时我们可以添加警告(只是永久警告)。 有一个开放的PR,我希望可以转变成类似的形式。 如果您想花时间在上面,我们通常会对PR感到满意。
在我看来,无论如何它都将转换为尽快开始弃用周期,我认为这将会发生(但是如果有人捡拾它会更快;)。 延迟请求的机会可能很小,但我对此表示怀疑,并且不尝试就很难知道。

所有32条评论

版本<= 1.16.0,有效

是的,这就是为什么要添加np.load(allow_pickle=True)原因,现在我想我们可以采取行动切换到默认值False并给出易于理解的消息“如果您要使用allow_pickle="True"信任此文件”。

我同意这将是更好的默认设置,因此我很乐意推动这种弃用,即使不幸的是它有点嘈杂,例如对于所有那些仅在实验室中共享一些数据(或只是保存/重新加载自己)的科学家而言。

因此,在2015年4月添加了allow_pickle ,因此自numpy 1.10起似乎应该已经存在。 因此,我认为这一举动现在变得更加现实,因为我怀疑许多使用/支持1.17的人是否还会支持1.10(消除了支持kwarg或不支持kwarg的痛苦)。 尽管目前看来scipy至少仍支持版本1中的1.8。

似乎会持续很长时间

如果您希望顺利过渡,建议您记录一个弃用警告并指定日期。

@Plazmaz当然,如果我们希望临时用户停止这样做,我会选择VisibleDeprecationWarning。 然后在一两个版本后弃用。 事实是,如果必须的话,解决该问题很烦人,并且在某些较旧的版本中不存在该kwarg。 因为那样的话,您必须执行if np.__version__ > ...: use kwarg else do not use kwarg来避免警告并同时支持两者。

无论如何,我认为您很有可能将其提高到1.17。 因此,如果您觉得自己有一个公开的PR,但我们可能想对邮件列表进行ping操作,看看是否有人抱怨。

嗨,Fedora numpy RPM维护者。 在发行包装中减轻这种情况的好方法是什么?

我不知道有什么好办法。 根据关注程度,我将很快添加警告,因此该警告肯定在1.17中出现。 如果有人非常担心,我们可以讨论将其反向移植或加快迁移的速度,但这将很大程度上取决于下游是否依赖它。

正在为此。

cc @jeanqasaur回复:安全/漏洞专业知识

嗨,Fedora numpy RPM维护者。 在发行包装中减轻这种情况的好方法是什么?

@limburgher :fedora对Python内置的完全相同的功能做了什么? 尚不清楚这是否需要缓解。

尽管我不反对更改默认值,但是将其声明为漏洞似乎是错误的。 它按照文档和设计的方式工作。

不幸的是,规则是,一旦分配了CVE编号,无论是否存在错误都不再重要,发行版必须尝试做一些事情向其客户证明他们正在提供价值。 不确定会发生什么,但是公司和运营人员一直在努力管理不断涌现的漏洞,而他们用来执行此操作的工具没有太多空间来传达细微差别,因此这就是压力的方式去。 不过,我们没有客户,因此我们不必将自身考虑在内。

我们可以在saveload判断特定文件是否使用了腌菜,对吗? 在这两种情况下,最好都迁移到allow_pickle=False在中间期间,我们会在确实需要saveload的情况下发出某种过时警告使用泡菜,未指定allow_pickle

@ eric-wieser与stdlib泡菜的区别在于,在大多数情况下, load / save实际上可以避免使用泡菜(例如,简单的基本类型数组); 只能在更特殊的情况下使用pickle,例如对象数组或IIRC某些复杂的dtypes。 这样,即使他们没有足够仔细地阅读文档,大多数使用安全案例的人也可能会错过不安全案例的存在。 而且无论如何,考虑到我们既有“安全模式”又有“不安全模式”,最好将“安全模式”设置为默认值。 对于stdlib泡菜OTOH,始终100%都是100%不安全的,因此不必担心默认值。

老实说,如果有文档记录是有意的功能,我可以出于良心关闭BZ,尤其是在默认情况下为安全的情况下。 我不知道我们如何处理Python的功能。 我看看

从我对规范的检查来看,我认为我们在这方面没有改变上游的任何内容。

CVE有争议吗? 这可能使维护者的情况更加清晰。

CVE在很大程度上似乎是伪造的。 numpy.load可以执行任意代码是众所周知的,有据可查,并且它是加载序列化的Python对象数组所必需的。 用户可以通过将allow_pickle=False传递给此库函数来禁止加载对象数组。

如果默认情况下只在显式询问时才加载对象数组会更好,但这是出于历史原因。 之前也曾建议过这种过渡,上面的讨论是关于如何以一种不会失控地破坏向后兼容性的方式进行的。

与Python酸洗类似,不小心使用numpy.load会导致下游应用程序中的漏洞。

numpy.load可以执行任意代码是众所周知的,有据可查,并且它是加载序列化的Python对象数组所必需的。

我只想说它已被记录。 我已经使用numpy几年了,虽然我不是numpy.save / numpy.load的频繁用户,但对于我来说, numpy.load并不是很明显遭受与pickle相同的漏洞。 当然,我不知道numpy.load可能会在后台使用pickle (我只使用numpy-native数组,并且从未想过, @ njsmith提到的情况就是

pickle易受攻击这一事实是众所周知的,它的文档上面有一个大红色警告。

警告pickle模块不能防止错误或恶意构建的数据。 切勿挑剔从不可信或未经身份验证的来源收到的数据。

相比之下, numpy.load的文档似乎在其allow_pickle关键字的描述中提到了整个安全性方面:

allow_pickle:_bool,可选_
允许加载存储在npy文件中的腌制对象数组。 禁止使用泡菜的原因包括安全性,因为加载泡菜数据可以执行任意代码。 如果不允许泡菜,则加载对象数组将失败。 默认值:True

如果我们可以在numpy.load的文档中加入Big Red Warning,至少在allow_pickle=False成为默认值之前,我不会讨厌它。 在做出更改之前,请注意numpy.load应该会升起同样的危险信号,即pickle.load升起。

欢迎使用文档PR, numpy.load

文档现在有关于泡菜的警告

不幸的是,规则是,一旦分配了CVE编号,无论是否存在错误都不再重要,发行版必须尝试做一些事情向其客户证明他们正在提供价值。 不确定会发生什么,但是公司和运营人员一直在努力管理不断涌现的漏洞,而他们用来执行此操作的工具没有太多空间来传达细微差别,因此这就是压力的方式去。

@njsmith并不是很糟糕:我们会将numpy.load默认设置为allow_pickleFalse ,这实际上并不是完全愚蠢的想法。

我看到的唯一风险是,未明确设置allow_pickle的任何项目都会中断。

我们不仅要担心最终用户项目-我担心下游库提供mylib.load来包装np.load 。 这些将开始无法加载对象数组。 它们将发生三件事之一:

  • 它们仍然被遗弃,并且永远不会像以前那样在对象数组上工作。 用户将发现他们的数据被劫持为人质,并且必须降级numpy才能恢复它。
  • 他们重新释放设置allow_pickle=True以恢复以前的行为-下游库表明他们认为这不是他们关心的攻击媒介。 这仍然使他们付出了不兼容的发布
  • 他们将在自己的API中公开allow_pickle=False ,将问题推向下游。

我的偏好是:

  • np.save不执行任何操作。 在保存对象数组的同时结束长时间运行的脚本崩溃是一种糟糕的经历。
  • np.load的默认值更改为None 。 检测用户未明确传递TrueFalse ,并发出UserWarning解释危险,要求他们在安全性( False )和对象之间进行选择数组支持( True )。 发出此警告后,默认为现状。 据我了解,这里的问题是缺乏认识。 在所有情况下,这两种选择都不正确,因此,我认为我们应该在没有警告的情况下突然改变默认值。

@ eric-wieser关于脚本崩溃的痛苦的要点。 默认情况下,我愿意提供UserWarning

问题是,从长远来看,我们想要在load 。 我不确定在阵列安全的时候我是否喜欢强迫所有人使用kwarg(使警告静音)。 尽管它确实没有将某人锁定在其数据之外的危险……OTOH,但是如果警告仅在“不安全”负载下显示,则为时已晚。 现在,我认为我稍微偏爱将过渡期延长一些。

OTOH,如果警告仅在“不安全”负载下显示,则可能为时已晚。

要么:

  • 库/脚本已经存在并已发布-我们所做的一切都为时已晚
  • 库/脚本仍在开发中。 开发人员应该在对安全文件进行本地测试期间看到警告,并且应该能够对他们想要的行为做出明智的决定。 因此,即使数组是安全的,我们也应发出警告(并且可能在加载之前,以防万一它们设置了与Python等价的-Werror )。

是的,我绝对同意使用库,但是对于大量较短的脚本,这可能会有些烦人。

np.load的默认值更改为None 。 检测未明确传递TrueFalse ,并发出UserWarning解释危险,要求他们在安全性( False )和对象之间进行选择数组支持( True )。 发出此警告后,默认为现状。 据我了解,这里的问题是缺乏认识。 在所有情况下,这两种选择都不正确,因此,我认为我们应该在没有警告的情况下突然改变默认值。

这听起来超级烦人。 我相信大多数人都不会保存/加载对象数组。 如果有人错过了警告,最坏的情况是(最终)脚本在加载时崩溃,数据仍然在磁盘上是安全的,然后使用allow_pickle标志重试。

是否首先尝试安全地加载并仅在由于对象数组而失败的情况下大喊大叫才是numpy的责任? 这将省去大多数(非客观)用例的额外工作,但我想那也会降低整个安全问题的可见性。 再说一次,我认为“应该非常注意用户”和“不应该给用户带来不便”在这里有点矛盾。

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

那这个补丁呢?

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

那这个补丁呢:

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

我仍然赞成在加载对象数据时发出警告,这可能有点“为时已晚”,但可以减少很多嘈杂的过渡。 保存时我们可以添加警告(只是永久警告)。 有一个开放的PR,我希望可以转变成类似的形式。 如果您想花时间在上面,我们通常会对PR感到满意。
在我看来,无论如何它都将转换为尽快开始弃用周期,我认为这将会发生(但是如果有人捡拾它会更快;)。 延迟请求的机会可能很小,但我对此表示怀疑,并且不尝试就很难知道。

您能否关闭此问题,因为https://nvd.nist.gov/vuln/detail/CVE-2019-6446中已提及,因此nexus iq仍然认为它存在漏洞

谢谢@ Manjunath07

此页面是否有帮助?
0 / 5 - 0 等级