← todos os artigos

Vitess corrigiu 14 falhas de segurança de uma vez — 9 são SQL injection

0

Em 13 de outubro de 2026, o projeto Vitess lançou patch simultâneo pras duas branches ativas — v24.0.5 e v23.0.8 — cobrindo 14 security advisories. Não é lista de rotina: nove dos 14 são variações de SQL injection, e a maioria delas não precisa de nenhum privilégio especial. Qualquer usuário autenticado no vtgate já basta.

Se você não conhece o Vitess: é a camada que várias empresas usam para fazer MySQL se comportar como um banco distribuído — sharding, replicação, failover e roteamento de query ficam escondidos atrás de duas peças, o vtgate (proxy que recebe a query da aplicação) e o vttablet (que fica na frente de cada shard do MySQL). A promessa central do projeto é que esse proxy aplica as regras de acesso — ACL de tabela, escopo de keyspace, limites de linha — antes de qualquer SQL chegar no MySQL real. É exatamente essa promessa que as nove falhas de injeção quebram: o SQL malicioso passa pelo proxy sem ser visto pelas checagens, e só é executado no MySQL de verdade.

O grupo que importa: SQL injection que atravessa o proxy sem ser percebido

Duas das nove merecem leitura técnica, porque mostram dois jeitos bem diferentes de contornar o parser.

GHSA-73pp-99vw-h5g8 (CVSS 7.6, alta) mora no VStream — o mecanismo de captura de mudanças de dados do Vitess. Um cliente autenticado abre um VStream e envia um valor LastPK (a chave primária do último registro lido) pra retomar a leitura de onde parou. O vtgate repassa esse valor sem validar; o vttablet confia no tipo declarado pelo próprio cliente em vez de checar contra o tipo real da coluna, e para valores numéricos escreve direto na cláusula WHERE sem escape. Como o VStream desliga timeouts de query, o atacante consegue injetar um UNION e ler qualquer tabela da instância — inclusive mysql.user — usando a conta de serviço vt_filtered, que tem SELECT e FILE em *.*. Com FILE, dá pra ler arquivos do servidor via LOAD_FILE e escrever via SELECT ... INTO OUTFILE. Não precisa de privilégio administrativo — só de conseguir abrir um VStream.

GHSA-pfg5-ppc7-ff45 (CVSS 8.8, alta) é mais sutil. O Vitess separa comentários finais (/* ... */) de uma query antes de autorizar e planejar, e reanexa o comentário depois, sem reenviar essa parte pelas checagens de ACL. A função que faz essa separação varre o texto de trás pra frente procurando o /* que abre o */ final — mas não confirma se esse é de fato o comentário correto, e ignora comentários de linha (--, #) e literais de string. Resultado: é possível montar uma query onde parte do SQL real fica escondida dentro do que o parser acha que é “comentário final”. Essa parte nunca é parseada, planejada nem autorizada — mas é enviada ao MySQL do jeito que está. O caminho via UNION funciona mesmo sem a conexão aceitar múltiplas instruções, então desabilitar CLIENT_MULTI_STATEMENTS não resolve esse caso.

As outras sete variações de injeção seguem o mesmo padrão de fundo — valor de entrada usado para montar SQL sem passar pelo parser/validador correto — em pontos diferentes: argumentos de convert_tz() em filtro do VStream (GHSA-92cc-q2h6-m2vr), nomes de tabela em Online DDL (GHSA-8w3p-4xg5-rm9w), caller ID em anotações de query quando --queryserver-config-annotate-queries está ativo (GHSA-x56j-8c72-5xgg), nome de variável em SET global (GHSA-m282-7w35-g77m), literais DATE/TIME/TIMESTAMP (GHSA-9248-hccp-qf8f), valor de sessão no hint SET_VAR (GHSA-9rx3-8pwm-c228) e bind variables numéricas malformadas (GHSA-xf67-9r78-xv82). O release notes não detalha CVSS de cada uma individualmente, mas a GitHub Advisory Database reporta todas em grau alto ou crítico — vale conferir o link de cada uma antes de decidir a prioridade do seu patch.

O grupo que não é injeção, mas também é controle de acesso furado

  • CSRF no VTAdmin (GHSA-3fr2-mqr5-r5x5, CVSS 4.2): rotas que mudam estado do cluster — PingTablet, RunHealthCheck, ConcludeTransaction, StartWorkflow, StopWorkflow, WorkflowSwitchTraffic, WorkflowDelete, MoveTablesComplete — aceitavam GET, e sem token anti-CSRF um site malicioso podia fazer o navegador de um operador logado disparar essas ações. Só afeta quem autentica o VTAdmin por cookie de sessão sem SameSite=Strict.
  • RBAC nunca verificado em ReloadSchemaShard (GHSA-78h7-x6qm-xpr8, CVSS 4.3): o handler foi copiado de outro que faz a checagem IsAuthorized, mas a checagem não veio na cópia. Só importa pra quem configurou RBAC no VTAdmin — sem RBAC configurado, não há barreira pra contornar.
  • Table ACL estrito com furo em roles wildcard (GHSA-c28j-qmfx-4gxp cobre parte disso): usuários com todas as roles em todas as tabelas ("%") conseguiam rodar DO, REPAIR, OPTIMIZE e CREATE TABLE parcialmente parseado mesmo quando a política deveria negar. CALL e LOAD DATA continuam bloqueados.
  • Charsets de conexão perigosos bloqueados: sjis, gbk, big5, ucs2, utf16 e afins deixam de ser aceitos — são os mesmos charsets historicamente usados em ataques de SQL injection por confusão de byte em outros bancos MySQL-compatíveis. Use utf8mb4.
  • VExplain exigindo ação execute: os modos que de fato rodam a query (QUERIES, ALL, TRACE) agora exigem permissão explícita; o padrão da UI passa a ser PLAN.

O que fazer

Se você roda Vitess, atualizar para 23.0.8 ou 24.0.5 não é opcional nem é “quando der” — a GHSA-73pp-99vw-h5g8 e a GHSA-pfg5-ppc7-ff45 sozinhas permitem ler qualquer tabela do MySQL subjacente, incluindo hashes de senha, a partir de um usuário autenticado comum, sem nenhum privilégio administrativo.

Enquanto o patch não sobe:

  • Não confie em “desabilitar multi-statement” como mitigação. Funciona pra algumas variações, mas a que usa UNION (incluindo a de comentário final) não depende de múltiplas instruções na conexão.
  • Se o VTAdmin estiver exposto, force SameSite=Strict no cookie de sessão ou configure o proxy de autenticação pra rejeitar navegação cross-site (checando Sec-Fetch-Site) até atualizar.
  • Audite suas regras de table ACL procurando roles com "%" — são elas que ficam expostas ao furo de DO/REPAIR/OPTIMIZE/CREATE TABLE.
  • Confira se --queryserver-config-annotate-queries está ativo nos seus tablets — é o flag que abre a superfície de injeção via caller ID.

Vale lembrar o contraste com o papel do Vitess: o projeto existe justamente pra impor essas regras de acesso entre a aplicação e o MySQL real. Um release com nove formas diferentes de contornar esse proxy é motivo pra tratar a atualização como incidente de segurança, não como manutenção de rotina — mesmo sem nenhum CVE formal atribuído até a publicação deste texto.

Fontes