python反序列化总结_Python代码审计实战案例总结之反序列
化和命令执⾏!
介绍
Python代码审计⽅法多种多样,但是总⽽⾔之是根据前⼈思路的迁移融合扩展⽽形成。⽬前Python代码审计思路,呈现分散和多样的趋势。Python微薄研发经验以及结合实际遇到的思路和技巧进⾏总结,以便于朋友们的学习和参考。
反序列化审计实战
反序列化漏洞在Python代码审计中属于常见⾼危漏洞之⼀,它的危害性根据执⾏环境略有不同,本地和远程分别为7.2和10的评分。通过评分也可得知漏洞危害是显⽽易见。那么咱们应该如何发现这个漏洞?关于发现此种漏洞要从反序列化的模块说起,Python的反序列化模块主要为pickle、cPickle、yaml等等。有关反序列化漏洞问题在多年前就被⼈们所发现,⽬前所看到的⼤多数反序列化漏洞是由于应⽤调⽤了存在问题的反序列化模块。那么咱们抓住寻反序列化模块则有可能会发现反序列化漏洞。
dask 命令执⾏漏洞(CNVD-2019-16789)
关于这个漏洞是笔者在2019年审计anaconda环境模块时候发现,提交CNVD通过验证,虽然是本地触发漏洞,但绝对是关于反序列化漏洞很好的案例,漏洞利⽤yaml模块问题进⾏反序列化。
漏洞分析
漏洞影响的版本 1.1.4 ,漏洞出现于dask模块中config.py⽂件,第139⾏。源于程序通过coolect_yaml⽅法中使⽤了yaml所导致的问题,⽅法⽤途从yaml⽂件收集配置。
其中第148⾏会判断是否为⽬录,传⼊⽂件就能继续执⾏。漏洞触发在第168⾏,使⽤了yaml.load执⾏了反序列化。
到此咱们通过POC触发存在反序列化的⽅法,即可造成代码执⾏问题。
漏洞POC
漏洞验证截图:
修复⽅法
yaml 在对于反序列化问题上,已经提供了安全反序列化的解决⽅法,程序使⽤yaml.safe_load可以进⾏安全的反序列化。咱们对于审计问题的修复建议根据实际情况使⽤。
NumPy 命令执⾏漏洞(CVE-2019-6446)
在NumPy 1.16.0版本之前存在反序列化命令执⾏漏洞,⽤户加载恶意的数据源造成代码执⾏。按照惯例在讲这个反序列化之前要说明Python的pickle的反序列化原理和栈指令。但不是本篇重点,故暂不讨论。
漏洞分析
咱们直接从代码层说起,漏洞的⼊⼝,lib/npyio.py 第288⾏附近。在这⾥存在使⽤反序列化模块的⽅法,并且allow_pickle值为True。allow_pickle 允许使⽤ Python pickles 保存对象数组,Python 中的 pickle ⽤于在保存到磁盘⽂件或从磁盘⽂件读取之前,对对象进⾏序列化和反序列化。通俗讲是个开关,并默认开启。
漏洞触发位置,位置在lib/npyio.py,第418⾏。这⾥有反序列化加载的⽅法。笔者将⼀些代码省略,直观看重点。默认格式要求ZIP⽂件前缀PK\x03\x04后缀PK\x05\x06,如果不满⾜默认的格式,则会执⾏pickle.load()反序列化⽅法。
到此执⾏流程为 NumPy.lib.npyio.py:load()=>pickle.py:load()。
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 pickle
if 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:
……
漏洞POC
综上所述,编写POC如下:
from numpy.lib import npyio
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,('whoami',))
tmpdaa = Test()
with open("test-file.pickle",'wb') as f:
pickle.dump(tmpdaa,f)
npyio.load("test-file.pickle")
测试结果如图:
命令执⾏审计实战
在Python模块中命令执⾏漏洞同样较为常见、危害较⼤。在审计命令执⾏时,⼤多时候程序可能会在满⾜特定条件下才能执⾏命令,也可能需要在不同的系统中才会执⾏命令,所以需要关注代码逻辑和某些特性。
numexpr 命令执⾏漏洞(CNVD-2019-17298)
Numexpr是机器学习模块NumPy的⼀个加速包,主要⽤于提⾼NumPy的性能。
漏洞分析
在该模块/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。根据代码逻辑:if os.WIFEXITED(status) and os.WEXITSTATUS(status) in
import picklesuccessful_status:所以successful_status =(True,0),并通过形参传⼊,最终导致命令执⾏问题。
漏洞POC
漏洞POC和执⾏结果:
dotenv 命令执⾏漏洞(CNVD-2019-17299)
dotenv是⼀个使Node.js从⽂件中加载环境变量的库。
漏洞分析
漏洞存在于dotenv 0.10.1版本中的main.py⽂件之中,第317⾏,可见该⽅法形参传⼊命令和环境变量。但是由于未对可⽤命令进⾏过滤导致任意命令执⾏问题。
漏洞POC
漏洞POC和执⾏结果:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。