Безопасность MODX, часть 2 - использование @ привязок

Это вторая часть доклада с конференции MODX Meetup Moscow. С первой частью про обход фильтрации MODX тегов можете ознакомиться тут.

@ операторы в ТВ параметрах


А теперь давайте перейдем к другой потенциальной проблеме безопасности — @ операторы в ТВ параметрах. Если о MODX тегах (про которые я рассказывал в первой части) знают все и кто-то даже пытаются их как-то фильтровать, то ситуация с ТВ резко меняется. Очень часто можно встретить решения, когда через какую-то форму на сайте создаются ресурсы в дереве документов. Как правило, подобную реализацию используют для сбора отзывов. Пару лет назад, мне для аудита безопасности предоставили сайт, на котором каждый заказ это отдельный документ.

Так вот опасность подобной реализации состоит в том, что @ операторы можно использовать не только в качестве “значения по умолчанию”, но еще и в качестве значения в каком-нибудь документе.

Чтобы вы точно поняли о чем я говорю — предлагаю посмотреть на демо-сайт.

Там есть документ (id = 5) в котором присутствует вывод ТВ параметра [[*checkpoint]]. При чем этот ТВ не связан ни с одним шаблоном, но несмотря на это, в базе значений ТВ параметров — modx_site_tmplvar_contentvalues хранится
@EVAL phpinfo();
И при просмотре страницы, код успешно выполняется.

На реальных сайтах, где используются визуальные редакторы и куча ТВ параметров, без мониторинга базы не найти закладку.

Но если выполнение произвольного кода через EVAL привязку можно отключить воспользовавшись системной настройкой allow_tv_eval, то другие — @ операторы уже не отключаемые. А именно
  • @DIRECTORY — Получение списка файлов в папке
  • @FILE — Чтение произвольных файлов
  • @SELECT — Выполнение запросов. При чем знать префикс таблиц вовсе не обязательно. Запросы можно строить используя плейсхолдеры [[+DBASE]] и [[+PREFIX]].
Поэтому рекомендация всего лишь одна — учитывать особенности движка и фильтровать пользовательские данные при создании документа. При чем при фильтрации стоит учитывать, что перед @ оператором могут стоять пробелы или символы табуляции, а регистр оператора не важен.

В случае же, если вы производите аудит безопасности или чистите сайт от вирусов — проверяйте значения по умолчанию у ТВ. Но самое главное, проверяйте таблицу значений ТВ параметров. Сделать это можно с помощью запросов
SELECT * FROM modx_site_tmplvar_contentvalues as stc WHERE stc.`value` REGEXP "^[[:space:]]*@";
# или
SELECT * FROM modx_site_tmplvar_contentvalues as stc WHERE trim(stc.`value`) LIKE '@%';
Найти значения ТВ параметров, которые имеют потерянные связи с ресурсами или шаблонами, можно при помощи запроса
SELECT stc.id, sc.id as content_id, stc.`value` as tv
FROM modx_site_tmplvar_contentvalues as stc
LEFT JOIN modx_site_content as sc ON sc.id = stc.contentid
WHERE NOT EXISTS (
	SELECT tmplvarid FROM modx_site_tmplvar_templates as stt WHERE stt.templateid = sc.template AND stc.tmplvarid = stt.tmplvarid;
)
x

@ операторы в шаблонах


Ну вот мы и добрались до самой латентной уязвимости.
Представьте следующую задачу: необходимо реализовать каталог, в котором можно будет переключиться с табличного варианта отображения на блочный или еще какой-нибудь.

Есть 2 варианта реализации подобного функционала — создать 2 разных страницы. Или принимать способ отображения через GET параметр. Выбирая второй способ можно допустить фатальную ошибку — ожидать имя чанка, при этом не задав white-лист.

Вот код уязвимого сниппета (используется getResources, но ничего не изменится если вместо него будет pdoResources):
$tpl = $modx->getOption(
    'tpl',
    $_REQUEST,
    $modx->getOption('tpl', $scriptProperties, 'DefaultChunk')
);

return $modx->runSnippet('getResources', [
    'parents' => 1,
    'tpl' => $tpl
]);

На первый взгляд ничего критичного. Но если вспомнить про поддержку inline шаблонов в различных сниппетах. А потом еще узнать про возможность загружать шаблоны из файла через оператор @FILE. То уязвимость становится очевидной — мы имеем дело с чтением произвольных файлов (документ с id = 6 на демо-сайте). Поэтому ни в коем случае нельзя давать пользователям право влиять на способ отображения, если вы не определили заранее список поддерживаемых чанков.
Евгений Борисов
30 сентября 2018, 22:23
8
648
+26

Комментарии: 5

Баха Волков
30 сентября 2018, 22:42
0
Очень значительно. Пойду переваривать информацию
Баха Волков
30 сентября 2018, 22:45
0
А я как раз задумывался и не мог понять почему у mFilter2 реализация разных шаблонов вывода сделана как она сделана, т.е. в GET передается &tpl=1, &tpl=2 и так далее
Иван Климчук
01 октября 2018, 14:47
0
@EVAL уже выпилен в 3.x, к слову, но совет «включать голову» актуален всегда.
    Евгений Борисов
    01 октября 2018, 18:25
    0
    Эффект от allow_tv_eval почти тот же. Но там и без @EVAL хватает операторов
    Pavel Zarubin
    01 октября 2018, 19:19
    +5
    Интересно, зачем? Прикрываться безопасностью — глупо, имея менеджерский доступ к админке можно получить суперпользователя десятками способов которые успешно перешли из REVO в MODX 3. Уже 100500 раз говорилось что если хотите себя обезопасить — делайте для менеджеров свою админку. Выпилив @EVAL ничего не изменилось, а вот удобство убавили в разы. Я лично через @EVAL генерировал динамические возможные значения тв поля