Баги в популярных CMS в последние месяцы стали настоящей напастью. Появление каждой такой уязвимости означает, что под угрозой оказываются сотни тысяч сайтов, и далеко не каждый владелец успевает вовремя обновиться до свежей версии. В этой статье мы изучим недавно обнаруженную дыру в CMS Joomla: из-за недостаточной фильтрации пользовательских данных система уязвима для SQL-инъекций.

Joomla 3.7.0, помимо множества улучшений и исправлений, принесла в ядро функцию пользовательских полей и, в частности, компонент com_fields. Как ты уже, наверное, догадался, этот новый компонент и стал причиной проблемы. Так что без лишних церемоний приступим к увлекательному путешествию в исходниках по следам уязвимости.

Детали уязвимости

В первую очередь заглядываем в сам файл контроллера.

/components/com_fields/controller.php

16: class FieldsController extends JControllerLegacy
17: {
...
27:     public function __construct($config = array())
28:     {
...
32:         if ($this->input->get('view') === 'fields' && $this->input->get('layout') === 'modal')
...
36:             $lang->load('com_fields', JPATH_ADMINISTRATOR);
37:
38:             $config['base_path'] = JPATH_COMPONENT_ADMINISTRATOR;

Сразу же бросается в глаза условие [32]: если view и layout принимают значения fields и modal соответственно, то CMS загружает администраторскую версию компонента com_fields. И все запросы от обычного пользователя будут проксироваться в него.

Что же нам это дает? Давай посмотрим.

Заглянем внутрь метода getListQuery, он занимается тем, что собирает запрос к базе данных. Нас интересует часть со строкой, в которой формируется сортировка (ORDER BY).

/administrator/components/com_fields/models/fields.php

124:    protected function getListQuery()
125:    {
...
304:        // Add the list ordering clause
305:        $listOrdering = $this->getState('list.fullordering', 'a.ordering');
306:        $orderDirn    = '';
307:
308:        if (empty($listOrdering))
309:        {
310:            $listOrdering  = $this->state->get('list.ordering', 'a.ordering');
311:            $orderDirn     = $this->state->get('list.direction', 'DESC');
312:        }
313:
314:        $query->order($db->escape($listOrdering) . ' ' . $db->escape($orderDirn));

Переменная $listOrdering — название поля в таблице, по которому требуется отсортировать запрос. Ее фильтрует функция escape, которая зависит от используемого на сервере драйвера для работы с БД. Она возвращает строку, в которой экранированы спецсимволы, в частности кавычки.

Рассмотрим исходный код этой функции для драйвера mysqli. Он встречается чаще всего, поскольку Joomla при установке предлагает именно его.

/libraries/joomla/database/driver/mysqli.php

242:    public function escape($text, $extra = false)
243:    {
244:        $this->connect();
245:
246:        $result = mysqli_real_escape_string($this->getConnection(), $text);
247:
248:        if ($extra)
249:        {
250:            $result = addcslashes($result, '%_');
251:        }
252:
253:        return $result;
254:    }

Для фильтрации используется функция mysqli_real_escape_string (строка 246), которая экранирует null-байты, переносы строк, одинарные и двойные кавычки. Однако в нашем случае это абсолютно бесполезные действия, так как в нашей переменной хранится название колонки для сортировки.

Давай посмотрим, как передать нужные нам значения в $listOrdering. Метод getState наследуется прямиком из абстрактного класса JModelLegacy, который является родителем для JModelList, а он, в свою очередь, наследуется нашим FieldsModelFields.

/administrator/components/com_fields/models/fields.php

019: class FieldsModelFields extends JModelList
...
305:        $listOrdering = $this->getState('list.fullordering', 'a.ordering');

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии