Безопасность 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
modx.pro
9
2 527
+26
Поблагодарить автора Отправить деньги

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

Баха Волков
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 генерировал динамические возможные значения тв поля
            Артем
            07 июня 2019, 21:19
            0
            А как тогда теперь задавать динамические возможные значения для тв? Неужели вешать плагин на пререндер?
            Александр Мельник
            07 июня 2019, 21:46
            -1
            Есть 2 варианта реализации подобного функционала — создать 2 разных страницы. Или принимать способ отображения через GET параметр.

            Ну почему же только две, это вы придумали две.
            Обычно это делает через куки и не нужно никаких get параметров
              Евгений Борисов
              09 июня 2019, 11:23
              0
              Если вы решили показать какой умный, то не удалось
              1) $_REQUEST это GET/POST/COOKIE
              2) Подменить данные в кукисах так же просто, как и в GET

              Еще вопросы?
                Александр Мельник
                09 июня 2019, 15:25
                0
                Евгений, вы слишком напряжены)
                Я не хотел никому демонстрировать, какой умный ибо чаще получается наоборот.
                Но прочтите что я написал, там ни слова о подменах кук и безопасности.
                Я просто уточнил, что способов при помощи которых на сайте можно переключить вид карточек товара больше чем 2 указанных вами и привел пример третьего.
                  Евгений Борисов
                  09 июня 2019, 16:32
                  0
                  Посмотрите внимательно пример уязвимого скрипта из статьи

                  $tpl = $modx->getOption(
                      'tpl',
                      $_REQUEST,
                      $modx->getOption('tpl', $scriptProperties, 'DefaultChunk')
                  );
                  Если я изменю текст с
                  Есть 2 варианта реализации подобного функционала — создать 2 разных страницы. Или принимать способ отображения через GET параметр.
                  на
                  Есть 2 варианта реализации подобного функционала — создать 2 разных страницы. Или принимать способ отображения через REQUEST параметр.
                  Вы по прежнему будете доказывать, что способов больше чем 2?
              Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
              10