
Exploit em Python para CVE-2026-21627, uma inclusão arbitrária de arquivo PHP não autenticada no Novarain Framework do Joomla, permitindo upload de arquivos, exclusão e RCE.
Inclusão Arbitrária de Arquivos Não Autenticada no Framework Novarain do Joomla (nrframework)
Uma vulnerabilidade crítica no plugin Tassos/Novarain Framework (plg_system_nrframework) do Joomla permite que atacantes não autenticados incluam arquivos PHP arbitrários no servidor, instanciem classes arbitrárias e encadeiem com classes gadget integradas para alcançar upload arbitrário de arquivos e exclusão arbitrária de arquivos — tudo sem autenticação.
| ID CVE | CVE-2026-21627 |
| Pontuação CVSS | 9.5 (Crítico) |
| Plugin | plg_system_nrframework (Tassos Framework / Novarain Framework) |
| Versões Vulneráveis | 4.10.14 até 6.0.37 |
| Corrigido Em | 6.0.38+ |
| CMS | Joomla 3.x, 4.x, 5.x |
O plugin nrframework é fornecido com várias extensões populares do Joomla da Tassos.gr, incluindo Convert Forms, Engage Box, Google Structured Data e outras.
O método ajaxTaskInclude() em nrframework.php é explicitamente incluído na lista de permissões para acesso de frontend (não-admin) por meio do array $non_admin_tasks. Ele aceita três parâmetros controlados pelo usuário:
path — usa o filtro de entrada RAW (zero sanitização, travessia de caminho possível)file — usa o filtro de entrada padrão do Joomlaclass — nome da classe a ser instanciada após a inclusãoO caminho concatenado $path . $file . '.php' é passado diretamente para @include_once, permitindo inclusão arbitrária de arquivos PHP. Após a inclusão, a classe especificada é instanciada e seu método onAJAX() é chamado com parâmetros controlados pelo usuário.
| Primitiva | Gadget | Gravidade | Descrição |
|---|---|---|---|
| Inclusão de Arquivo | ajaxTaskInclude() | Crítico | Incluir qualquer arquivo .php no servidor |
| Exclusão de Arquivo | JFormFieldNRInlineFileUpload::onRemove() | Crítico | unlink() sem validação de caminho — excluir qualquer arquivo gravável pelo servidor web |
| Upload de Arquivo | JFormFieldNRInlineFileUpload::onUpload() | Alto | Enviar arquivos de texto para qualquer diretório gravável acessível pela web |
| Divulgação de Caminho | Resposta de upload | Médio | Caminho completo do sistema de arquivos vazado na resposta JSON |
python3 cve_2026_21627.py --target <URL> --mode <MODO> [OPÇÕES]
| Modo | Descrição | Risco |
|---|---|---|
verify | Confirmar se a vulnerabilidade existe | Seguro / Somente leitura |
upload | Enviar um arquivo para um diretório controlado | Médio |
delete | Excluir um arquivo arbitrário no servidor | Destrutivo |
rce | Tentar cadeia completa de RCE (upload + execução) | Alto |
info | Incluir arquivo PHP arbitrário para reconhecimento | Médio |
Verificar vulnerabilidade:
python3 cve_2026_21627.py --target https://example.com --mode verify
Enviar arquivo de prova de conceito:
python3 cve_2026_21627.py --target https://example.com --mode upload --shell-type txt
Enviar shell SSI (requer Apache mod_include):
python3 cve_2026_21627.py --target https://example.com --mode upload --shell-type shtml
Tentar cadeia RCE:
python3 cve_2026_21627.py --target https://example.com --mode rce --cmd "id"
Excluir um arquivo (destrutivo):
python3 cve_2026_21627.py --target https://example.com --mode delete --file-path /var/www/html/test.txt
--target, -t URL alvo (obrigatório)
--mode, -m Modo de exploração: verify|upload|delete|rce|info (obrigatório)
--sef-prefix Prefixo de URL SEF do Joomla (padrão: /it/)
--delay Atraso entre requisições em segundos (padrão: 2.5)
--proxy Proxy HTTP (ex.: http://127.0.0.1:8080)
--no-ssl-verify Desabilitar verificação de certificado SSL
Modo upload:
--shell-type Tipo de arquivo: shtml|csv|txt|html (padrão: shtml)
--upload-dir Diretório de upload relativo a JPATH_ROOT (padrão: images)
--custom-content Conteúdo personalizado do arquivo a ser enviado
Modo delete:
--file-path Caminho completo no servidor do arquivo a ser excluído
Modo RCE:
--cmd Comando a ser executado (padrão: id)
Modo info:
--php-path Caminho do arquivo PHP relativo a JPATH_SITE
--php-file Nome do arquivo PHP sem a extensão .php
--php-class Classe PHP a ser instanciada
┌──────────────┐ ┌───────────────────┐ ┌─────────────────────┐
│ Atacante │───>│ onAjaxNrframework │───>│ ajaxTaskInclude() │
│ │ │ (roteador AJAX) │ │ │
│ task=include │ │ include está em │ │ path = entrada RAW │
│ path=... │ │ $non_admin_tasks │ │ @include_once $path │
│ file=... │ │ (sem necessidade │ │ new $class()->onAJAX│
│ class=... │ │ de autenticação) │ └──────────┬──────────┘
└──────────────┘ └───────────────────┘ │
v
┌─────────────────────────────────────┐
│ JFormFieldNRInlineFileUpload │
│ (classe gadget) │
│ │
│ onAjax() ──> onUpload() [GRAVAR] │
│ ──> onRemove() [EXCLUIR] │
└─────────────────────────────────────┘
include é chamada com um path controlado (filtro RAW = sem sanitização) apontando para o arquivo gadget.JFormFieldNRInlineFileUpload fornece onUpload() para gravação de arquivos e onRemove() para exclusão de arquivos, ambos com validação de entrada insuficiente.requestspip install requests
Monitore os logs de acesso para tentativas de exploração:
# Padrão de log Apache/Nginx
grep -E "option=com_ajax.*plugin=nrframework.*task=include" access.log
Regra WAF — Bloquear requisições que correspondam a:
option=com_ajax.*plugin=nrframework.*task=include.*path=
Auditoria pós-comprometimento:
images/ e outros diretórios graváveis para arquivos inesperadosconfiguration.php e .htaccess@include_onceajaxTaskInclude() completamente e o substitui por um registro estrito de manipuladores (AjaxHandlerRegistry)| Data | Evento |
|---|---|
| 2026-02 | Vulnerabilidade descoberta durante teste de penetração autorizado |
| 2026-02 | Exploit criado |
| 2026-02 | Divulgação pública |
Esta ferramenta é fornecida apenas para testes de segurança autorizados e fins educacionais. Use este exploit somente contra sistemas para os quais você tenha permissão escrita explícita para testar. O acesso não autorizado a sistemas de computador é ilegal. O autor não assume nenhuma responsabilidade por uso indevido.
Yallasec — yallasec.com
Arcangelo Saracino — @arkango