
Injection SQL dans PyAthena via DefaultParameterFormatter (CVE-2026-65321)
Sévérité : Critique, CVSS v4.0 9.3 / CVSS v3.1 9.8 (attribué par VulnCheck, le CNA)
Vecteur (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
Vecteur (v3.1) : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Affecté : PyAthena <= 3.35.3 (toutes les versions jusqu'à la 3.35.3 incluse)
Corrigé dans : 3.35.4
CWE : CWE-89 (Mauvaise neutralisation des éléments spéciaux utilisés dans une commande SQL, « Injection SQL »)
Signalé par : Rahul Karne
CNA : VulnCheck
Publié : 3 août 2026
PyAthena échappait correctement les entrées non fiables dans les requêtes SELECT et incorrectement dans les requêtes DELETE.
PyAthena, le client Python DB-API largement utilisé pour Amazon Athena, sélectionne sa routine d'échappement de chaînes en fonction du mot-clé d'ouverture de l'instruction. Les instructions commençant par SELECT, WITH, INSERT, UPDATE ou MERGE reçoivent un échappement correct pour Trino, dans lequel un guillemet simple est neutralisé en le doublant (''). Toute autre instruction, le plus souvent un DELETE ou un CREATE TABLE … AS SELECT (CTAS), retombe sur l'échappement par antislash de style Hive (\'). Le moteur d'Athena est Trino, qui traite un antislash à l'intérieur d'une chaîne entre guillemets simples comme un caractère ordinaire, de sorte que l'échappement par antislash ne neutralise rien. Un attaquant qui peut influencer un paramètre de chaîne dans une telle instruction peut terminer le littéral et injecter du SQL arbitraire, sans authentification et sans interaction de l'utilisateur.
La faille est donc absente du chemin de lecture et présente précisément dans les types d'instructions destructives où elle cause le plus de dégâts. Le paquet est téléchargé 22,3 millions de fois par mois.
PyAthena est une bibliothèque cliente communautaire tierce pour Amazon Athena. Ce n'est pas un produit AWS, et il ne s'agit pas d'une vulnérabilité dans AWS ni dans Athena lui-même.
Un attaquant qui contrôle un paramètre de chaîne transmis à une instruction vulnérable peut sortir du littéral de chaîne prévu et modifier la logique de l'instruction. L'impact le plus direct et le plus facilement démontrable est la suppression non autorisée de données : une charge utile telle que missing' OR 1=1 -- dans une requête DELETE … WHERE token = %(token)s neutralise le prédicat WHERE et supprime toutes les lignes que le rôle IAM du workgroup Athena est autorisé à supprimer (par exemple, toutes les lignes d'une table Iceberg). Selon le type d'instruction et les permissions du rôle, un attaquant peut également être en mesure de créer des tables définies par l'attaquant via l'injection CTAS et, lorsqu'il peut ensuite lire la table résultante, d'exfiltrer des données d'autres tables auxquelles le rôle a accès.
Tout l'impact est délimité par les permissions du workgroup Athena / du rôle IAM qu'utilise le client. Il s'agit d'une injection dans le plan de données du moteur SQL d'Athena ; elle ne permet pas l'exécution de code sur l'hôte exécutant PyAthena, ni le compromis d'AWS lui-même.
Qui est concerné : Les applications utilisant PyAthena < 3.35.4 avec le DefaultParameterFormatter par défaut (substitution de paramètres pyformat / named côté client) qui (1) construisent une instruction ne commençant pas par SELECT/WITH/INSERT/UPDATE/MERGE, en pratique DELETE, CTAS, CREATE VIEW, DROP ou ALTER, et (2) transmettent des données influencées par l'attaquant comme paramètre de chaîne à cette instruction.
Qui n'est pas concerné :
3.35.4 ou une version ultérieure.SELECT/WITH/INSERT/UPDATE/MERGE ; celles-ci passent par l'échappeur sûr à doublement de guillemets.| Métrique | Valeur | Source |
|---|---|---|
| Téléchargements cumulés | 740.6M | pepy.tech/projects/pyathena |
| Téléchargements, 30 derniers jours | 22.3M | pepy.tech |
| Téléchargements, 24 dernières heures | 221.0K | pepy.tech |
| Taux d'installation continu | 8.95/second | pepy.tech |
| Projets en aval notables | dbt-athena importe _escape_hive et _escape_presto directement depuis pyathena.formatter | connections_legacy.py#L23-L27 |
DefaultParameterFormatter.format() sélectionne la fonction d'échappement de chaînes uniquement à partir du mot-clé d'ouverture de l'instruction. Seule une liste blanche de préfixes reçoit l'échappeur correct pour Trino ; toute autre instruction retombe sur l'échappement par antislash de style Hive.
# 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}'"
Le moteur SQL d'Amazon Athena est Trino (Presto dans les versions antérieures du moteur). Dans Trino, le seul échappement pour un guillemet simple à l'intérieur d'un littéral de chaîne entre guillemets simples est de le doubler ('') ; un antislash est un caractère littéral. _escape_hive ne neutralise donc pas du tout un guillemet pour Athena ; il émet ... = 'missing\' OR 1=1 -- ', que Trino analyse comme le littéral de chaîne 'missing\' suivi de OR 1=1 -- ', c'est-à-dire du SQL contrôlé par l'attaquant.
La conception est dangereuse en cas de défaillance (fail-dangerous) : elle met le chemin sûr en liste blanche et fait retomber tout le reste par défaut sur l'échappeur non sûr. Le correctif en amont inverse cette logique pour être sûr par défaut (fail-safe) (échappeur Trino par défaut ; échappement Hive uniquement pour le DDL Hive authentique tel que CREATE DATABASE/DROP TABLE/MSCK REPAIR, tout en traitant CTAS et CREATE VIEW comme du Trino), et supprime en outre les commentaires SQL de tête afin qu'un préfixe /* … */ DELETE … ne puisse pas déjouer la détection du type d'instruction.
_escape_hive n'est pas une sanitisation manquante, c'est de la sanitisation. C'est une routine d'échappement correcte et bien formée pour la grammaire des littéraux de chaîne de Hive, appliquée à un moteur qui utilise celle de Trino. Les outils d'analyse par suivi de flux (taint tracking) modélisent l'injection SQL comme des données non fiables atteignant un puits sans passer par un échappeur ; ici, les données passent par un échappeur sur tous les chemins, et l'échappeur ressemble exactement à du code de remédiation parce que c'en est un, mais pour le mauvais dialecte.