
Iniezione SQL in PyAthena tramite DefaultParameterFormatter (CVE-2026-65321)
Gravità: Critica, CVSS v4.0 9.3 / CVSS v3.1 9.8 (assegnati da VulnCheck, il CNA)
Vettore (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
Vettore (v3.1): CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Versioni interessate: PyAthena <= 3.35.3 (tutte le versioni fino alla 3.35.3)
Corretta in: 3.35.4
CWE: CWE-89 (Improper Neutralization of Special Elements used in an SQL Command, 'SQL Injection')
Segnalato da: Rahul Karne
CNA: VulnCheck
Pubblicato: 3 agosto 2026
PyAthena ha applicato correttamente l'escape degli input non attendibili nelle query SELECT e in modo errato nelle query DELETE.
PyAthena, il client Python DB-API ampiamente utilizzato per Amazon Athena, seleziona la propria routine di escape delle stringhe in base alla parola chiave iniziale dell'istruzione. Le istruzioni che iniziano con SELECT, WITH, INSERT, UPDATE o MERGE ricevono un escape corretto per Trino, in cui un apice singolo viene neutralizzato raddoppiandolo (''). Ogni altra istruzione, più comunemente una DELETE o una CREATE TABLE … AS SELECT (CTAS), ricade nell'escape in stile Hive con backslash (\'). Il motore di Athena è Trino, che tratta un backslash all'interno di una stringa racchiusa tra apici singoli come un carattere ordinario, quindi l'escape con backslash non neutralizza nulla. Un aggressore che può influenzare un parametro stringa in tale istruzione può terminare il letterale e iniettare SQL arbitrario, senza autenticazione e senza interazione con l'utente.
La vulnerabilità è quindi assente dal percorso di lettura ed è presente esattamente nei tipi di istruzione distruttivi dove causa il maggior danno. Il pacchetto viene scaricato 22,3 milioni di volte al mese.
PyAthena è una libreria client comunitaria di terze parti per Amazon Athena. Non è un prodotto AWS e questa non è una vulnerabilità in AWS o in Athena stesso.
Un aggressore che controlla un parametro stringa passato a un'istruzione vulnerabile può uscire dal letterale di stringa previsto e alterare la logica dell'istruzione. L'impatto più diretto e dimostrabile in modo affidabile è la cancellazione non autorizzata di dati: un payload come missing' OR 1=1 -- in una query DELETE … WHERE token = %(token)s neutralizza il predicato WHERE ed elimina ogni riga che il ruolo IAM del workgroup Athena è autorizzato a eliminare (ad esempio, tutte le righe di una tabella Iceberg). A seconda del tipo di istruzione e dei permessi del ruolo, un aggressore potrebbe anche essere in grado di creare tabelle definite dall'aggressore tramite iniezione CTAS e, laddove possa successivamente leggere la tabella risultante, di esfiltrare dati da altre tabelle accessibili al ruolo.
Tutto l'impatto è limitato dai permessi del workgroup Athena / ruolo IAM utilizzato dal client. Si tratta di un'iniezione sul piano dati nel motore SQL di Athena; non consente l'esecuzione di codice sull'host che esegue PyAthena, né la compromissione di AWS stesso.
Chi è interessato: applicazioni che utilizzano PyAthena < 3.35.4 con il DefaultParameterFormatter predefinito (sostituzione dei parametri pyformat / named lato client) che (1) costruiscono un'istruzione che non inizia con SELECT/WITH/INSERT/UPDATE/MERGE, in pratica DELETE, CTAS, CREATE VIEW, DROP o ALTER, e (2) passano dati influenzati dall'aggressore come parametro stringa a tale istruzione.
Chi non è interessato:
3.35.4 o successiva.SELECT/WITH/INSERT/UPDATE/MERGE: queste vengono instradate verso l'escaper sicuro con raddoppio delle virgolette.| Metrica | Valore | Fonte |
|---|---|---|
| Download, da sempre | 740.6M | pepy.tech/projects/pyathena |
| Download, ultimi 30 giorni | 22.3M | pepy.tech |
| Download, ultime 24 ore | 221.0K | pepy.tech |
| Tasso di installazione sostenuto | 8.95/second | pepy.tech |
| Downstream degno di nota | dbt-athena importa _escape_hive e _escape_presto direttamente da pyathena.formatter | connections_legacy.py#L23-L27 |
DefaultParameterFormatter.format() seleziona la funzione di escape delle stringhe esclusivamente in base alla parola chiave iniziale dell'istruzione. Solo una allowlist di prefissi riceve l'escaper corretto per Trino; ogni altra istruzione ricade nell'escape in stile Hive con backslash.
# 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}'"
Il motore SQL di Amazon Athena è Trino (Presto nelle versioni precedenti del motore). In Trino, l'unico escape per un apice singolo all'interno di un letterale di stringa racchiuso tra apici singoli è raddoppiarlo (''); un backslash è un carattere letterale. _escape_hive quindi non neutralizza affatto un apice per Athena: emette ... = 'missing\' OR 1=1 -- ', che Trino interpreta come il letterale di stringa 'missing\' seguito da OR 1=1 -- ', cioè SQL controllato dall'aggressore.
Il design è fail-dangerous: mette in allowlist il percorso sicuro e fa ricadere ogni altra cosa nell'escaper non sicuro per impostazione predefinita. La correzione upstream inverte questo comportamento rendendolo fail-safe (usa per impostazione predefinita l'escaper Trino; usa l'escape Hive solo per DDL Hive genuino come CREATE DATABASE/DROP TABLE/MSCK REPAIR, trattando CTAS e CREATE VIEW come Trino) e inoltre rimuove i commenti SQL iniziali, così un prefisso /* … */ DELETE … non può vanificare il rilevamento del tipo di istruzione.
_escape_hive non è priva di sanitizzazione: è sanitizzazione. È una routine di escape corretta e ben formata per la grammatica dei letterali di stringa di Hive, applicata a un motore che usa quella di Trino. Gli strumenti di taint tracking modellano l'iniezione SQL come dati non attendibili che raggiungono un sink senza passare attraverso un escaper; qui i dati passano attraverso un escaper su ogni percorso, e l'escaper assomiglia esattamente a codice di rimedio perché è codice di rimedio, per il dialetto sbagliato.
La correttezza del dialetto non è una proprietà di taint, quindi nessuna regola di taint la valuta. Il difetto è strutturalmente invisibile a CodeQL, Semgrep, Snyk e Socket, non semplicemente trascurato da essi: è per questo che è persistito in un pacchetto installato circa nove volte al secondo.
Un aggressore ha bisogno di: