
SQL-Injection in PyAthena über DefaultParameterFormatter (CVE-2026-65321)
Schweregrad: Kritisch, CVSS v4.0 9.3 / CVSS v3.1 9.8 (vergeben von VulnCheck, der CNA)
Vektor (v4.0): CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Vektor (v3.1): CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Betroffen: PyAthena <= 3.35.3 (alle Versionen bis einschließlich 3.35.3)
Behoben in: 3.35.4
CWE: CWE-89 (Unsachgemäße Neutralisierung spezieller Elemente in einem SQL-Befehl, 'SQL-Injection')
Gemeldet von: Rahul Karne
CNA: VulnCheck
Veröffentlicht: 3. August 2026
PyAthena hat nicht vertrauenswürdige Eingaben in SELECT-Abfragen korrekt und in DELETE-Abfragen inkorrekt escaped.
PyAthena, der weit verbreitete Python-DB-API-Client für Amazon Athena, wählt seine String-Escaping-Routine anhand des führenden Schlüsselworts der Anweisung aus. Anweisungen, die mit SELECT, WITH, INSERT, UPDATE oder MERGE beginnen, erhalten Trino-korrektes Escaping, bei dem ein einfaches Anführungszeichen durch Verdopplung ('') neutralisiert wird. Jede andere Anweisung – meist ein DELETE oder ein CREATE TABLE … AS SELECT (CTAS) – fällt auf Hive-artiges Backslash-Escaping (\') zurück. Die Engine von Athena ist Trino, das einen Backslash innerhalb einer in einfache Anführungszeichen gesetzten Zeichenkette als gewöhnliches Zeichen behandelt; Backslash-Escaping neutralisiert folglich nichts. Ein Angreifer, der einen String-Parameter in einer solchen Anweisung beeinflussen kann, kann das Literal beenden und beliebiges SQL injizieren – ohne Authentifizierung und ohne Benutzerinteraktion.
Der Fehler fehlt daher im Lesepfad und ist genau in den destruktiven Anweisungstypen vorhanden, wo er den größten Schaden anrichtet. Das Paket wird 22,3 Millionen Mal pro Monat heruntergeladen.
PyAthena ist eine Community-Client-Bibliothek von Drittanbietern für Amazon Athena. Es ist kein AWS-Produkt, und dies ist keine Schwachstelle in AWS oder in Athena selbst.
Ein Angreifer, der einen String-Parameter kontrolliert, der an eine anfällige Anweisung übergeben wird, kann aus dem beabsichtigten String-Literal ausbrechen und die Logik der Anweisung verändern. Die direkteste und am zuverlässigsten demonstrierbare Auswirkung ist unbefugtes Löschen von Daten: Ein Payload wie missing' OR 1=1 -- in einer DELETE … WHERE token = %(token)s-Abfrage neutralisiert das WHERE-Prädikat und löscht jede Zeile, die die IAM-Rolle des Athena-Workgroups löschen darf (z. B. alle Zeilen einer Iceberg-Tabelle). Je nach Anweisungstyp und den Berechtigungen der Rolle kann ein Angreifer darüber hinaus über CTAS-Injection vom Angreifer definierte Tabellen erstellen und – sofern er die resultierende Tabelle anschließend lesen kann – Daten aus anderen Tabellen exfiltrieren, auf die die Rolle zugreifen kann.
Alle Auswirkungen sind durch die Berechtigungen des Athena-Workgroups / der IAM-Rolle begrenzt, die der Client verwendet. Es handelt sich um eine Data-Plane-Injection in die SQL-Engine von Athena; sie führt nicht zu Codeausführung auf dem Host, auf dem PyAthena läuft, und auch nicht zur Kompromittierung von AWS selbst.
Wer betroffen ist: Anwendungen, die PyAthena < 3.35.4 mit dem standardmäßigen DefaultParameterFormatter (clientseitige pyformat- / named-Parametersubstitution) verwenden und (1) eine Anweisung erstellen, die nicht mit SELECT/WITH/INSERT/UPDATE/MERGE beginnt – in der Praxis DELETE, CTAS, CREATE VIEW, DROP oder ALTER – und (2) vom Angreifer beeinflusste Daten als String-Parameter an diese Anweisung übergeben.
Wer nicht betroffen ist:
3.35.4 oder neuer verwendet.SELECT/WITH/INSERT/UPDATE/MERGE beginnen; diese werden zum sicheren Escaper mit Anführungszeichen-Verdopplung geleitet.| Metrik | Wert | Quelle |
|---|---|---|
| Downloads, insgesamt | 740,6 Mio. | pepy.tech/projects/pyathena |
| Downloads, letzte 30 Tage | 22,3 Mio. | pepy.tech |
| Downloads, letzte 24 Stunden | 221,0K | pepy.tech |
| Anhaltende Installationsrate | 8,95/Sekunde | pepy.tech |
| Nennenswerte Downstream-Projekte | dbt-athena importiert _escape_hive und _escape_presto direkt aus pyathena.formatter | connections_legacy.py#L23-L27 |
DefaultParameterFormatter.format() wählt die String-Escaping-Funktion ausschließlich anhand des führenden Schlüsselworts der Anweisung aus. Nur eine Allowlist von Präfixen erhält den Trino-korrekten Escaper; jede andere Anweisung fällt auf Hive-artiges Backslash-Escaping zurück.
# src/pyathena/formatter.py, DefaultParameterFormatter.format(), lines ~271-275 (v3.35.2)
operation_upper = operation.upper()
if operation_upper.startswith(("SELECT", "WITH", "INSERT", "UPDATE", "MERGE")):
escaper = _escape_presto # safe: doubles single quotes
else:
escaper = _escape_hive # UNSAFE for Trino: backslash-escapes quotes
# src/pyathena/formatter.py, lines ~157-165 (v3.35.2)
def _escape_hive(val: str) -> str:
escaped = (
val.replace("\\", "\\\\")
.replace("'", "\\'") # produces \' (not a quote escape in Trino)
.replace("\r", "\\r")
.replace("\n", "\\n")
.replace("\t", "\\t")
)
return f"'{escaped}'"
Die SQL-Engine von Amazon Athena ist Trino (in früheren Engine-Versionen Presto). In Trino ist der einzige Escape für ein einfaches Anführungszeichen innerhalb eines in einfache Anführungszeichen gesetzten String-Literals die Verdopplung (''); ein Backslash ist ein literales Zeichen. _escape_hive neutralisiert daher für Athena überhaupt kein Anführungszeichen – es erzeugt ... = 'missing\' OR 1=1 -- ', was Trino als das String-Literal 'missing\' gefolgt von OR 1=1 -- ' parst, also als vom Angreifer kontrolliertes SQL.
Das Design fällt im Fehlerfall gefährlich aus (fail-dangerous): Es führt den sicheren Pfad auf einer Allowlist und setzt für alles andere standardmäßig den unsicheren Escaper ein. Der Upstream-Fix kehrt dies in fail-safe um (standardmäßig den Trino-Escaper verwenden; Hive-Escaping nur für echte Hive-DDL wie CREATE DATABASE/DROP TABLE/MSCK REPAIR, während CTAS und CREATE VIEW als Trino behandelt werden) und entfernt zusätzlich führende SQL-Kommentare, damit ein /* … */ DELETE …-Präfix die Erkennung des Anweisungstyps nicht aushebeln kann.
_escape_hive vermisst keine Sanitisierung – es ist Sanitisierung. Es ist eine korrekte, wohlgeformte Escaping-Routine für die String-Literal-Grammatik von Hive, angewendet auf eine Engine, die Trinos Grammatik verwendet. Taint-Tracking-Werkzeuge modellieren SQL-Injection als nicht vertrauenswürdige Daten, die eine Senke erreichen, ohne durch einen Escaper zu laufen; hier durchlaufen die Daten auf jedem Pfad einen Escaper, und der Escaper sieht exakt wie Remediation-Code aus, weil er Remediation-Code ist – nur für den falschen Dialekt.
Dialektkorrektheit ist keine Taint-Eigenschaft, daher bewertet sie keine Taint-Regel. Der Defekt ist für CodeQL, Semgrep, Snyk und Socket strukturell unsichtbar und nicht nur übersehen – weshalb er in einem Paket überleben konnte, das etwa neunmal pro Sekunde installiert wird.
Ein Angreifer benötigt:
< 3.35.4 mit dem standardmäßigen clientseitigen Parameter-Formatter verwendet (pyformat- / named-Paramstyle).SELECT/WITH/INSERT/UPDATE/MERGE beginnt – in der Praxis DELETE oder CTAS.Numerische Parameter sowie jede Anweisung, die an den sicheren Escaper geleitet wird, sind über diesen Fehler nicht ausnutzbar.
Der PoC ruft den echten, unveränderten PyAthena-Formatter auf (importiert aus der veröffentlichten PyPI-Version, keine Rekonstruktion) und führt dessen Ausgabe gegen eine lokale In-Memory-DuckDB-Datenbank aus. Kein AWS-Konto, keine Anmeldedaten, kein Netzwerkzugriff. Die vollständige Reproduktion besteht aus zwei Befehlen:
pip install pyathena==3.35.2 duckdb
python poc_pyathena_cna_demo.py --no-pause
Quelle: poc_pyathena_cna_demo.py
Aufgezeichnete Demo: Demo ansehen
Der Docstring von DefaultParameterFormatter besagt, dass er Parameter escaped, um SQL-Injection zu verhindern. Der PoC gibt diesen Docstring aus und druckt anschließend _escape_presto, _escape_hive und den Präfix-Auswahlzweig direkt aus dem installierten Paket per inspect.getsource – der Leser sieht den Widerspruch also im Quellcode der Bibliothek selbst, statt dem Advisory aufs Wort zu glauben.
DELETE-Prädikat-DurchbruchVom Angreifer kontrollierter Parameter: missing' OR 1=1 --
DELETE FROM sessions WHERE token = 'missing\' OR 1=1 -- '
Trinos Lexer kennt genau einen Escape für ein einfaches Anführungszeichen innerhalb eines in einfache Anführungszeichen gesetzten String-Literals: die Verdopplung (''). Ein Backslash hat keine Escaping-Bedeutung. Das Literal endet daher an dem Anführungszeichen nach missing\, und OR 1=1 -- wird als SQL geparst. DuckDB teilt diese Eigenschaft, und gegen eine mit zwei Zeilen befüllte sessions-Tabelle ist das Ergebnis:
Rows before executing generated SQL: 2
Rows after executing generated SQL: 0
Das WHERE-Prädikat ist neutralisiert und jede Zeile wird gelöscht.
Vom Angreifer kontrollierter Parameter: nobody' UNION SELECT secret FROM admin_credentials --
CREATE TABLE leaked AS SELECT name FROM users WHERE name = 'nobody\' UNION SELECT secret FROM admin_credentials -- '
Das injizierte UNION kopiert eine Zeile aus einer Tabelle, auf die sich die ursprüngliche Anweisung nie bezogen hat. In der Demo landet DEMO_SECRET_VALUE aus admin_credentials in der für den Angreifer sichtbaren leaked-Tabelle. Bei Athena ist dies durch das begrenzt, was die IAM-Rolle des Workgroups lesen kann.
Dieselben Payloads, die über SELECT und UPDATE geleitet werden, erreichen _escape_presto und werden durch Anführungszeichen-Verdopplung korrekt neutralisiert:
SELECT name FROM users WHERE name = 'nobody'' UNION SELECT secret FROM admin_credentials -- '
UPDATE update_control SET token = 'x'' OR 1=1 -- ' WHERE id = 999
Beide Payloads bleiben innerhalb des String-Literals. SELECT liefert null Zeilen und UPDATE ändert null Zeilen – kein Durchbruch. Diese Kontrollen belegen, dass die Testumgebung solide ist und dass der Defekt spezifisch für die Escaper-Auswahl ist und nicht für das Test-Setup.
Dieselben drei Payloads gegen 3.35.4 erzeugen alle Ausgaben mit verdoppelten Anführungszeichen:
DELETE FROM sessions WHERE token = 'missing'' OR 1=1 -- '
CREATE TABLE leaked AS SELECT name FROM users WHERE name = 'nobody'' UNION SELECT secret FROM admin_credentials -- '
Der Fix übersteht auch ein Präfix mit führendem Kommentar, das andernfalls die Erkennung des Anweisungstyps aushebeln würde:
/* hi */ DELETE FROM sessions WHERE token = 'missing'' OR 1=1 -- '
In jedem Fall bleibt der Payload als Daten enthalten und es findet keine Injection statt.
Führen Sie ein Upgrade auf PyAthena 3.35.4 oder neuer durch:
pip install --upgrade "pyathena>=3.35.4"
Wenn Sie nicht sofort aktualisieren können: Übergeben Sie keine nicht vertrauenswürdigen Daten als Parameter an Anweisungen, die nicht mit SELECT/WITH/INSERT/UPDATE/MERGE beginnen. Validieren bzw. allowlisten Sie bei destruktiven Anweisungen die Eingabe serverseitig oder führen Sie die Operation über einen Pfad aus, der nicht auf den clientseitigen Formatter angewiesen ist. Es gibt kein Konfigurations-Flag, das die Escaper-Auswahl in betroffenen Versionen ändert; ein Upgrade ist die zuverlässige Lösung.
Hinweis für Projekte, die die Escaper direkt importieren. Der Fix in 3.35.4 ändert die Escaper-Auswahl innerhalb von DefaultParameterFormatter.format(). Er ändert _escape_hive selbst nicht, das weiterhin per Design korrekt-für-Hive und falsch-für-Trino bleibt. Jedes Downstream-Projekt, das _escape_hive oder _escape_presto aus pyathena.formatter importiert und ein eigenes Statement-Typ-Dispatch durchführt, ist durch ein PyAthena-Upgrade daher nicht behoben und sollte seine eigene Dispatch-Logik anhand derselben Dialektfrage prüfen.
So prüfen Sie, ob Sie betroffen sind:
pip show pyathena # check the installed version
pip-audit # flags CVE-2026-65321 once it propagates to the advisory feeds
VulnCheck (die CNA) hat zwei Scores veröffentlicht, beide Kritisch: CVSS v4.0 = 9.3 (CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N) und CVSS v3.1 = 9.8 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H).
Der Angriff ist remote und ohne Authentifizierung, ohne Benutzerinteraktion (AV:N/PR:N/UI:N) und erfordert keine besonderen angrifferseitigen Voraussetzungen (AC:L/AT:N). Die Auswirkung auf das verwundbare System ist in Bezug auf Vertraulichkeit, Integrität und Verfügbarkeit hoch (VC:H/VI:H/VA:H in v4.0; C:H/I:H/A:H in v3.1): Ein injiziertes DELETE kann Daten zerstören, und ein injiziertes CTAS/UNION SELECT kann Daten lesen und kopieren, auf die die Rolle des Workgroups zugreifen kann. Im v4.0-Vektor sind die Metriken für nachgelagerte Systeme alle None (SC:N/SI:N/SA:N) – der Fehler ist auf Athenas SQL- und Autorisierungsgrenze beschränkt und führt nicht zu Codeausführung auf dem Host oder einem Pivot in AWS selbst. Genau dieses SC/SI/SA:N-Triple ist der Grund, warum v4.0 bei 9.3 statt bei einem ausgereizten 10.0 landet, und es ist die ehrliche Antwort auf die Frage „bedeutet das eine vollständige Systemkompromittierung?“ – nein, das tut es nicht. Der v3.1-Score erreicht 9.8, weil sein binäres Scope-Flag (S:U/S:C) in einem einzigen Bit zusammenfasst, was v4.0 auf drei separate nachgelagerte Systemmetriken verteilt; die beiden Scores sind konsistent, nicht widersprüchlich.
Eine Einschränkung, die proaktiv erwähnt werden sollte: Die reale Ausnutzbarkeit erfordert, dass die konsumierende Anwendung nicht vertrauenswürdige Eingaben in eine parametrisierte Nicht-SELECT-Anweisung (DELETE/CTAS/DROP/ALTER) leitet, und der konkrete Blast Radius ist durch die IAM-Berechtigungen des Athena-Workgroups begrenzt. Der Base Score modelliert den angemessenen Worst Case; ein Deployment nach dem Least-Privilege-Prinzip ist weniger stark betroffen.
| Datum | Ereignis |
|---|---|
| 19. Juli 2026 | Schwachstelle identifiziert |
| 20. Juli 2026 | Dem Maintainer gemeldet |
| 20. Juli 2026 | Maintainer bestätigt |
| 31. Juli 2026 | Fix committet |
| 31. Juli 2026 | Gepatchte Version 3.35.4 veröffentlicht |
| 2. August 2026 | CVE-2026-65321 von VulnCheck vergeben |
| 3. August 2026 | Öffentliche Offenlegung |
Entdeckt und gemeldet von Rahul Karne, Sicherheitsforscher und IEEE Senior Member. Seine Forschung konzentriert sich auf Injection- und Eingabeverarbeitungsfehler in stark genutzten Open-Source-Paketen; frühere Offenlegungen umfassen CVEs in confluent-kafka (1,12 Mrd. Downloads), datamodel-code-generator (185 Mio.) und dem WordPress-Plugin ElementsKit Elementor Addons (über 1 Mio. aktive Installationen).
Kontakt: [email protected] · GitHub: rahulreddykarne
Presseanfragen: [email protected]. Demoaufzeichnung in hoher Auflösung, PoC und zusätzliche technische Details auf Anfrage verfügbar.