
Ein PoC zur Demonstration von CVE-2026-25604
Host-Header-Injection führt zu einem SAML-Authentifizierungs-Bypass im AWS Auth Manager von Apache Airflow
Ein Angreifer kann einen bösartigen Host-Header in den SAML-Login-Ablauf injizieren, wodurch die URL des Assertion Consumer Service (ACS) auf einen vom Angreifer kontrollierten Server zeigt. Dadurch kann der Angreifer gültige SAML-Antworten abfangen und diese erneut abspielen, um unbefugten Zugriff auf die betroffene Airflow-Instanz zu erlangen – oder Token über verschiedene Airflow-Instanzen mit unterschiedlichen Zugriffskontrollen hinweg wiederverwenden.
| Paket | Betroffen | Behoben |
|---|---|---|
apache-airflow-providers-amazon | 8.0.0 – 9.21.x | 9.22.0 |
CVE-2026-25604: Ursprungsvalidierungsfehler im AWS Auth Manager (CWE-346)
Im AWS Auth Manager wurde der Ursprung der SAML-Authentifizierung wie vom Client bereitgestellt verwendet und nicht gegen die tatsächliche Instanz-URL überprüft. Dadurch war es möglich, durch Wiederverwendung von SAML-Antworten anderer Instanzen Zugriff auf verschiedene Instanzen mit potenziell unterschiedlichen Zugriffskontrollen zu erlangen.
— NVD
| Quelle | Link |
|---|---|
| NVD | https://nvd.nist.gov/vuln/detail/CVE-2026-25604 |
| Behebungs-PR | https://github.com/apache/airflow/pull/61368 |
Der AWS Auth Manager von Apache Airflow verwendet für die Authentifizierung SAML 2.0 über AWS IAM Identity Center. Beim Erstellen der SAML-Authentifizierungsanfrage liest die Methode _prepare_flask_request() den Host-Header direkt aus der eingehenden HTTP-Anfrage, um die ACS-Callback-URL zu erstellen:
# 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,
...
}
Die resultierenden Werte http_host und server_port werden verwendet, um die SAML-AssertionConsumerService-URL zu konstruieren. Da der Identitätsanbieter (IdP) dieser URL vertraut, leitet er den authentifizierten Benutzer – zusammen mit der signierten SAML-Antwort – dorthin weiter, wohin der Host-Header zeigt.
┌──────────┐ ┌──────────────┐ ┌─────────────┐
│ 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! │ │
│<─────────────────────│ │
└──────────────────────┴────────────────────────┘
Szenario A – Token-Diebstahl per Phishing: Ein Angreifer sendet einen präparierten Login-Link (mit gefälschtem Host-Header über einen Reverse-Proxy) an einen legitimen Benutzer. Nachdem der Benutzer sich bei IAM Identity Center authentifiziert hat, wird die SAML-Antwort an den Server des Angreifers umgeleitet. Der Angreifer spielt sie gegen die echte Airflow-Instanz erneut ab.
Szenario B – Instanzübergreifende Token-Wiederverwendung: In Multi-Tenant- oder Multi-Instanz-Airflow-Umgebungen kann eine gültige SAML-Antwort von Instanz A gegen Instanz B erneut abgespielt werden. Da der Ursprung nie gegen die tatsächliche Instanz-URL validiert wird, werden unterschiedliche Zugriffskontrollen auf Instanz B umgangen.
CVE-2026-25604-PoC/
├── README.md # This file
└── mock_airflow.py # Mock vulnerable Airflow server
pip install flask python3-saml
Richten Sie eine SAML-2.0-Anwendung in AWS IAM Identity Center ein, wie in der Dokumentation zum Airflow AWS Auth Manager beschrieben:
http://<airflow-host>:<port>/login_callbackaws-auth-manager-saml-clientpython mock_airflow.py <SAML_METADATA_URL> [PORT]
Zum Beispiel:
python mock_airflow.py https://portal.sso.us-east-1.amazonaws.com/saml/metadata/XXXX 8080
Führen Sie in einem separaten Terminal eine SAML-Anmeldung mit manipuliertem Host-Header aus:
curl -v -H "Host: attacker.com:9090" http://127.0.0.1:8080/login
Der Server antwortet mit einer 302 Redirect-Weiterleitung zur Anmeldeseite von AWS IAM Identity Center. Untersuchen Sie die SAML-AuthnRequest – die AssertionConsumerService-URL wird auf attacker.com:9090/login_callback zeigen, anstatt auf den legitimen Server.
Auf der Konsole des Mock-Airflow-Servers:
[LOGIN] Host header: attacker.com:9090
[DEBUG] http_host=attacker.com, server_port=9090
Die SAML-AuthnRequest weist den IdP nun an, die authentifizierte SAML-Antwort an attacker.com:9090 zu übermitteln, wodurch der Angreifer ein gültiges Token zum erneuten Abspielen erhält.
airflow/providers/amazon/aws/auth_manager/aws_auth_manager.py – die Methode _prepare_flask_request():
host = request.headers.get("Host", request.host)
Diese Zeile vertraut dem vom Client bereitgestellten Host-Header, ohne ihn gegen die konfigurierte Airflow-Basis-URL (AIRFLOW__API__BASE_URL) zu validieren.
Der Fix (PR #61368, zusammengeführt am 3. Februar 2026) ersetzt den aus der Anfrage abgeleiteten Host durch den Wert aus der Airflow-Konfiguration:
- host = request.headers.get("Host", request.host)
+ host = conf.get("api", "base_url")
Dadurch wird sichergestellt, dass die ACS-URL immer mit der tatsächlichen, vom Administrator konfigurierten Instanz-URL übereinstimmt, unabhängig davon, welchen Host-Header der Client sendet.
Dieses Proof-of-Concept dient ausschließlich pädagogischen und autorisierten Sicherheitstestzwecken. Verwenden Sie es verantwortungsvoll und nur gegen Systeme, die Ihnen gehören oder für die Sie eine ausdrückliche Testberechtigung haben.
| Behebungs-Commit | 1a86aec |