
phpMyAdmin 5.2.3 - Alta - Remoto - CSRF - remoção de token em /sql
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-csrf-sql
Classe: CSRF Alcance: Remoto
phpMyAdmin 5.2.3 (tag RELEASE_5_2_3, commit 962857e). Common.php constrói a requisição PSR-7 a partir de globals antes de checkTokenRequestParam. Em caso de incompatibilidade, Sanitize::removeRequestVars limpa $_POST e $_GET, mas não esse snapshot. $sql_query é então copiado de $request->getParsedBodyParam('sql_query'). POSTs AJAX abortam em caso de incompatibilidade de token. POSTs não-AJAX continuam. SqlController prefere o $_POST['sql_query'] removido e, caso contrário, mantém o global.
Uma vítima com cookie de sessão do phpMyAdmin é suficiente. Faça POST em index.php?route=/sql com sql_query e sem token válido, e sem ajax_request. O SELECT é executado como aquele usuário MySQL. O padrão CookieSameSite=Strict no 5.2.3 bloqueia muitos navegadores entre sites. Same-site, Lax, None ou autenticação HTTP ainda atingem. De qualquer forma, este é um controle CSRF quebrado.
| ID | sem CVE ainda |
| Classe | CSRF |
| Alcance | Remoto. O padrão CookieSameSite=Strict bloqueia muitos navegadores entre sites. Same-site / Lax / None / autenticação HTTP permanecem. |
| CWE | CWE-352 |
| CVSS | Alto: 8.1 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N |
| Produto | phpMyAdmin |
| Afetado | 5.2.3 tag RELEASE_5_2_3 (962857e) |
| Autenticação | Cookie de sessão do phpMyAdmin da vítima (ou autenticação HTTP). Sem token CSRF válido. |
| Licença | GNU Affero GPL v3.0 |
| Lab | apenas 127.0.0.1:19240 |
Qualquer um que consiga fazer o navegador da vítima enviar um POST para o phpMyAdmin sem ajax_request pode executar SQL como aquele usuário MySQL.
| Privilégio | Método / caminho | Comprovado em lab ou inferido |
|---|---|---|
| Executar SQL do atacante como a conta MySQL da vítima (integridade + reconhecimento daquele SQL box) | POST index.php?route=/sql sql_query=... db=... sem token, sem ajax_request | Comprovado em lab. O corpo dos resultados continha PMA-CSRF-SQL-WITNESS. O log geral mostrou o SELECT como appuser |
| Abortar o mesmo handler em AJAX | Mesmo POST com ajax_request=1 | Comprovado em lab. Token mismatch. Linha marcadora do INSERT ausente. O log geral não executou aquele INSERT |
Ignorar handlers que apenas leem o $_POST removido | POST /database/structure/drop-table sem token | Comprovado em lab. keepme ainda presente |
Mesma lacuna em export (SaveDir), DROP/TRUNCATE de partição, bloqueio de conta, /config/set, criação de pmadb | Qualquer handler que leia o corpo PSR-7 após a remoção | Inferido. Não exercitado |
Fechado neste lab: PMA não autenticado (login por cookie necessário primeiro), rotas AJAX (elas saem em caso de incompatibilidade), drop-table sem token, shell do SO. O padrão Strict SameSite significa que um formulário clássico entre sites muitas vezes não enviará o cookie; o resíduo ainda é uma verificação CSRF falha em same-site e em implantações Lax/None.
Oito buscas paralelas no código-fonte de RELEASE_5_2_3. Common.php cria $request = createFromGlobals() antes de checkTokenRequestParam(). Em caso de incompatibilidade, Sanitize::removeRequestVars() limpa apenas $_POST/$_GET. Não-AJAX continua. SqlController usa o global $sql_query se $_POST estiver vazio. Rota GET|POST /sql.
Caminhos errados: tratar o AJAX /sql como o resíduo (ele aborta com Token mismatch); tratar o drop-table como o resíduo (esse handler apenas lê o $_POST removido); tratar o padrão Strict SameSite como "CSRF está fechado" (o controle ainda está quebrado; same-site / Lax / None permanecem).
python3 phpmyadmin-csrf-sql-Abraxas-Labs.py
ou
cd lab
./run.sh
Apenas loopback: http://127.0.0.1:19240. Imagens phpmyadmin:5.2.3 e mysql:8.0. Projeto Compose phpmyadmin-csrf-sql. O PoC é um POST loopback same-site (Strict SameSite ainda envia o cookie). Witness PMA-CSRF-SQL-WITNESS.
SUCCESS phpmyadmin-csrf-sql sql-ran=yes ajax-abort=yes drop-held=yes PMA-CSRF-SQL-WITNESS
Em caso de incompatibilidade, substitua a requisição por um corpo vazio, ou recuse todos os POSTs, não apenas AJAX. Não copie sql_query de uma requisição obsoleta. Falhe de forma fechada como no logout.
962857e)libraries/classes/Common.php snapshot da requisição antes da remoção do tokenSanitize::removeRequestVars limpa apenas $_POST/$_GETSqlController global $sql_queryGNU Affero GPL v3.0. Veja LICENSE. Apenas lab loopback. Sem garantia.