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»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»