1。介绍Python代码审计的方法多种多样,但总而言之,都是在对以往思想的迁移、融合和扩展的基础上形成的。目前,Python代码审计思路呈现去中心化、多元化的趋势。将Python微薄的研发经验和实践中遇到的思路和技巧总结出来,方便朋友们学习和参考。2、反序列化审计实战反序列化漏洞是Python代码审计中常见的高危漏洞之一。其危害性根据执行环境略有不同。本地和远程分数分别为7.2和10。从分数上也可以知道,漏洞危害是显而易见的。那么我们应该如何找到这个漏洞呢?这种漏洞的发现是从反序列化模块开始的。Python的反序列化模块主要有pickle、cPickle、yaml等。反序列化漏洞的问题在很多年前就已经被发现,而现在看到的大多数反序列化漏洞都是由于应用程序调用了有问题的反序列化模块造成的。那么如果我们抓住反序列化模块,就有可能发现反序列化漏洞。1、dask命令执行漏洞(CNVD-2019-16789)该漏洞是作者在2019年审计anaconda环境模块时发现的,提交CNVD验证通过。该漏洞虽然是本地触发的,但肯定与反序列化漏洞有关。本例中,该漏洞利用yaml模块的问题进行反序列化。(1)漏洞分析受漏洞影响的1.1.4版本出现在dask模块中的config.py文件,第139行,问题源于程序在coolect_yaml方法中使用yaml,从yaml文件中收集配置。其中第148行会判断是否是目录,传入文件即可继续执行。漏洞在第168行触发,使用yaml.load进行反序列化。此时我们通过POC触发反序列化方法,会导致代码执行出现问题。(2)漏洞POC漏洞验证截图:(3)修复方法yaml已经针对反序列化问题提供了安全反序列化解决方案,程序使用yaml.safe_load进行安全反序列化。我们对修复审计问题的建议要根据实际情况使用。2、NumPy命令执行漏洞(CVE-2019-6446)NumPy1.16.0版本之前存在反序列化命令执行漏洞,用户加载恶意数据源导致代码执行。按照惯例,在讲这个反序列化之前,有必要先解释一下Python的pickle的反序列化原理和入栈指令。但不是本文的重点,所以暂且不谈。(1)漏洞分析我们直接从代码层开始,漏洞的入口,lib/npyio.py的288行附近。这里有一个使用反序列化模块的方法,allow_pickle值为True。allow_pickle允许使用Pythonpickle保存对象数组,在Python中使用pickle在保存到磁盘文件或从磁盘文件读取之前序列化和反序列化对象。通俗的说就是一个开关,默认是开启的。漏洞触发位置,位置为lib/npyio.py,第418行。下面介绍如何反序列化加载。作者省略了部分代码,直接看重点。默认格式需要ZIP文件的前缀PK\x03\x04和后缀PK\x05\x06。如果不满足默认格式,就会执行pickle.load()反序列化方法。到目前为止的执行过程是NumPy.lib.npyio.py:load()=>pickle.py:load()。尝试:#CodetodistinguishfromNumPybinaryfilesandpickles._ZIP_PREFIX=b'PK\x03\x04'_ZIP_SUFFIX=b'PK\x05\x06'#emptyzipfilesstartwiththis......ifmagic.startswith(_ZIP_PREFIX)ormagic.startswith(_ZIP_SUFFIX):......elifmagic==_PREFAT.MAG:...else:#Tryapickleifnotallow_pickle:raiseValueError("Cannotloadfilecontainingpickleddata""whenallow_pickle=False")try:returnpickle.load(fid,**pickle_kwargs)exceptException:raiseIOError("Failedtointerpretfile%sasapickle"%repr(file))finally:...(2)漏洞POC总结一下,写POC如下:fromnumpy.libimportnpyiofromnumpyimport__version__print(__version__)importosimportpickleclassTest(object):def__init__(self):self.a=1def__reduce__(self):return(os.system,('whoami',))tmpdaa=Test()withopen("test-file.pickle",'wb')asf:pickle.dump(tmpdaa,f)npyio.load("测试文件.pickle")测试结果如图:3.CommandExecutionAudit实战Python模块中的Commandexecution漏洞也很常见,危害也很大。在审计命令执行时,很多时候,程序可能只在满足某些条件时才执行命令,或者可能需要在不同的系统中执行,因此需要注意代码逻辑和某些特性。1.numexpr命令执行漏洞(CNVD-2019-17298)Numexpr是机器学习模块NumPy的加速包,主要用于提升NumPy的性能。(1)漏洞分析在模块/numexpr/cpuinfo.py的第37行,有一个执行命令的方法。getoutput是有问题的方法。该命令通过逻辑在.popen中执行,但是由于os.WIFEXITED(status)和os.WEXITSTATUS(status)只在linux下支持,所以在windows下执行会报错。Linux下,当status为全局变量,赋值为0时,os.WIFEXITED(status)的结果为True,os.WEXITSTATUS(status)的结果为0。根据代码逻辑:如果os.WIFEXITED(status)和os.WEXITSTATUS(status)中的successful_status:所以successful_status=(True,0),并且通过形参传入,最终会导致命令执行出现问题。(二)漏洞POC漏洞POC及执行结果:2.dotenv命令执行漏洞(CNVD-2019-17299)dotenv是一个实现Node.js从文件加载环境变量的库。(1)漏洞分析漏洞存在于dotenv0.10.1版本的main.py文件中,第317行,可以看出该方法的形参传入命令和环境变量。但是任意命令执行有一个问题,因为没有过滤可用的命令。(2)漏洞POC漏洞POC及执行结果:总结通过以上案例和总结,相信可以进一步提高Python审计的能力。这些漏洞在Python审计中较为典型,如有文中疏忽,望指正。
