Хаки и дополнения. Последовательность работы (выполнения) компонентов Joomla Бездоказательный weblinks php

Точка входа в Joomla! компонент подобна у большинства компонентов. Для этого примера мы будем использовать один из компонентов ядра Joomla – Web Links (Ссылки на сайты). Первый файл, который будет выполнен во front-end: …/components/com_weblinks/weblinks.php .

Сначала мы видим проверку безопасности, предназначенную для уверенности, что никто не сможет вызвать эту страницу непосредственно. Это стандарт, который должен использоваться во всех ваших php-файлах (хотя есть несколько исключений):

Мы проверяем строку запроса, чтобы посмотреть, было ли отправлено определенное название контроллера. Если так, мы удостоверяемся, что можем загрузить необходимый файл в каталоге контроллеров:

// Require specific controller if requested if ($controller = JRequest:: getWord ("controller" ) ) { $path = JPATH_COMPONENT. DS. "controllers" . DS. $controller . ".php" ; if (file_exists ($path ) ) { require_once $path ; } else { $controller = "" ; } }

Теперь мы создаем экземпляр класса нашего контроллера, используя имя, которое определили выше:

Как только задача выполнена, производим редирект, если он требуется:

// Redirect if set by the controller $controller -> redirect () ;
Класс контроллера (Controller Class)

Общий (характерный) контроллер для компонента ссылок находится здесь: …/components/com_weblinks/controller.php .
Весь этот класс определяет метод display, который является используемым по умолчанию, если пользователь не определяет другую задачу (task).

defined ("_JEXEC" ) or die ( "Restricted access" ) ; jimport("joomla.application.component.controller" ) ; /** * Weblinks Component Controller * * @package Joomla * @subpackage Weblinks * @since 1.5 */ class WeblinksController extends JController { /** * Method to show a weblinks view * * @access public * @since 1.5 */ function display() { // Set a default view if none exists if ( ! JRequest:: getCmd ( "view" ) ) { JRequest:: setVar ("view" , "categories" ) ; } //update the hit count for the weblink if (JRequest:: getCmd ("view" ) == "weblink" ) { $model =& $this -> getModel ("weblink" ) ; $model -> hit () ; } // View caching logic -- simple... are we logged in? $user = & JFactory:: getUser () ; $view = JRequest:: getVar ("view" ) ; $viewcache = JRequest:: getVar ("viewcache" , "1" , "POST" , "INT" ) ; if ($user -> get ("id" ) || ($view == "category" && $viewcache == 0 ) ) { parent:: display (false ) ; } else { parent:: display (true ) ; } } }

В этом методе мы устанавливаем вид (представление) по умолчанию: показ категорий, если другой вид не был передан как параметр строки запроса. Если требуемый вид — weblink, мы увеличиваем значение счетчика просмотра ссылки. Затем мы устанавливаем значение переменной вида и вызываем метод diplay нашего родительского класса JController .
Стоит обратить отдельное внимание на вызов метода getModel. Он загружает необходимую модель для компонента . В рассматриваемом примере, этот метод загрузит модель weblink, находущуюся здесь: …/components/com_weblinks/models/weblink.php .
Здесь условимся, что мы не запрашивали определенное представление, и поэтому наш вид будет установлен в categories.
Затем, мы открываем класс представления.

Класс представления (вида) (View Class)

Так как мы предполагаем, что хотим представление категорий, это — следующий файл, который будет выполнен: …/components/com_weblinks/views/categories/view.html.php

// Check to ensure this file is included in Joomla! defined ( "_JEXEC" ) or die ( "Restricted access" ) ; jimport( "joomla.application.component.view" ) ; /** * HTML View class for the WebLinks component * * @static * @package Joomla * @subpackage Weblinks * @since 1.0 */ class WeblinksViewCategories extends JView { function display( $tpl = null ) { global $mainframe ; $document =& JFactory:: getDocument () ; $categories =& $this -> get ("data" ) ; $total =& $this -> get ("total" ) ; $state =& $this -> get ("state" ) ; // Get the page/component configuration $params = & $mainframe -> getParams () ; $menus = & JSite:: getMenu () ; $menu = $menus -> getActive () ; // because the application sets a default page title, we need to get it // right from the menu item itself if (is_object ( $menu ) ) { $menu_params = new JParameter( $menu -> params ) ; if (! $menu_params -> get ( "page_title" ) ) { $params -> set ("page_title" , JText:: _( "Web Links" ) ) ; } } else { $params -> set ("page_title" , JText:: _( "Web Links" ) ) ; } $document -> setTitle ( $params -> get ( "page_title" ) ) ; // Set some defaults if not set for params $params -> def ("comp_description" , JText:: _("WEBLINKS_DESC" ) ) ; // Define image tag attributes if ($params -> get ("image" ) != - 1 ) { if ($params -> get ("image_align" ) != "" ) $attribs [ "align" ] = $params -> get ("image_align" ) ; else $attribs [ "align" ] = "" ; $attribs [ "hspace" ] = 6 ; // Use the static HTML library to build the image tag $image = JHTML:: _("image" , "images/stories/" . $params -> get ("image" ) , JText:: _("Web Links" ) , $attribs ) ; } for ($i = 0 ; $i < count ($categories ) ; $i ++ ) { $category =& $categories [ $i ] ; $category -> link = JRoute:: _("index.php?option=com_weblinks&view=category&id=" . $category -> slug ) ; // Prepare category description $category -> description = JHTML:: _("content.prepare" , $category -> description ) ; } $this -> assignRef ("image" , $image ) ; $this -> assignRef ("params" , $params ) ; $this -> assignRef ("categories" , $categories ) ; parent:: display ($tpl ) ; } } ?>

И снова, это — очень простой класс с одним методом display. БОльшая часть логики здесь является специфической для компонента ссылок, но если присмотреться можно найти функциональность используемую в большинстве классов представлений компонентов. В конце метода display этот класс вызывает родительский (JView) метод display , передавая название шаблона для отображения. Если название шаблона отображения не передается, используется шаблон «default».
И в последних, мы открываем класс шаблона.

Класс шаблона (Template Class)

Условимся что определенное имя шаблона не было передано, таким образом будет использован шаблон по умпочанию «default». В этом случае, следующий файл, который будет рассмотрен: …/components/com_weblinks/views/categories/tmpl/default.php
-> escape ($this -> params -> get ("page_title" ) ) ; ?>

  • ( )

Большая часть логики здесь специфична для выполняемого компонента. Также по коду видно, что в этом файле весь HTML, смешан с PHP – таковы его особенность о предназначение.

Другие файлы, использующиеся в компонентах

Несколько из других типов файла Вы могли бы найти в компонентах:

  • Helpers — в компонентах зачастую используется файл helper.php или каталог helpers со многими файлами. Эти файлы обычно содержат только общие функциональные возможности для компонента.
  • Assets — это, кажется, всеобъемлющая папка для других файлов, включаемых в компонент.
  • router.php — этот файл используется, при включенной настройке SEF URL, для трансляции URL в обоих направлениях (в человеко-понятный с псевдонимами и в системный вид Joomla с параметрами).
  • xml-файлы — они обычно определяют параметры и другую информацию о компоненте, и его обозрение. Они используются, например, при создании пунктов меню компонента.
  • index.html — хорошая практика иметь пустой index.html файл во всех ваших каталогах. Это такая пассивная мера безопасности.
  • css/images/js — папки, которые содержат различные файлы для внедрения дизайна и функциональности на стороне клиента (в браузере).

Браузер YRC Weblink создан и распространяется индийской софтверной компанией YRC Group Inc. И потому в качестве домашней страницы по умолчанию стоит индийский Google:))

Индийские программисты считаются одними из самых крутых в мире (после русских и китайских:), но с этим браузером у них что-то не заладилось, ибо это просто праздник какой-то, а не браузер. Идеи, которые они постарались воплотить в этом браузере - прекрасны, но сама реализация из рук вон плоха. Браузер работает "через пень-колоду", то есть странно и плохо. Попробовал его на двух разных компьютерах - под Windows 7 и под Windows 8 - и там и там глюки и зависания.

Впрочем, пойдем по порядку.

После установки браузер предлагает выбрать некоторые настройки (как, например, видно на скриншоте выше), а кроме того - создать аккаунт для облачной синхронизации и хранения настроек, закладок, заметок и файлов.

Прекрасная идея! Жму ссылку Sign Up, что значит "Зарегистрироваться", открывается сайт с веселенькими картинками, но открывается он почему-то не в YRC Weblink, а в браузере, который стоит на компьютере по умолчанию и это первая странность. Другая странность заключается в том, что нужно вводить довольно много своих данных - зачем? Например, в браузере Maxthon для регистрации в облаке требуется ввести лишь email и пароль, что гораздо проще, приятнее и не вызывает лишних вопросов.

Ладно, ввожу все эти данные. Приходит письмо для подтверждения аккаунта, жму на ссылку, однако сайт сообщает мне "Oops! - не нахожу твоих данных в базе". Но тут приходит еще одно письмо с новой ссылкой, жму на ссылку в нем и опять - Oops! Однако, в процессе этих упсов приходит третье письмо и там написано - поздравляем, ваш аккаунт подтвержден! Такая вот своеобразная индийская верификация аккаунта.

Открываю браузер, настройки, пытаюсь импортировать закладки. Браузер в упор не видит закладочного файла формата.html, который все известные мне браузеры видят, понимают и принимают без проблем. Ввожу название файла вручную, жму Импортировать и получаю отчет - закладки успешно импортированы!

Вот только куда они успешно импортированы??? Ни в браузере, ни в облаке их нет. Повторяю операцию еще раз и тот же результат. Ладно, проехали. Двигаемся дальше.

В облаке и настройках есть пункт Заметки. Помня про заметки в браузере Maxthon, которые можно создавать с помощью встроенного блокнота и которые автматически сохраняются в облаке, пытаюсь найти нечто подобное в YRC Weblink, увы, безрезультатно. Просмотр заметок есть, а инструмента для их создания нет. Странно? Еще как!

Ну ОК. Смотрим, что у нас есть еще. При инсталляции браузер самостоятельно (без спросу) установил на рабочий стол два ярлыка - ярлык браузера (это нормально) и ярлык Твиттера.

При нажатии на этот ярлык открывается отдельное окно браузера с Твиттером. Какого черта это делать да еще по умолчанию? Может, я вообще не пользуюсь Твиттером? Ладно, ярлык Твиттера с рабочего стола удалил, но не тут-то было! Теперь, при нажатии на ярлык браузера (а не твиттера), в панели задач браузер высвечивается Твиттером! Такого праздничного глюка я еще в своей жизни не встречал!

Кстати, об этих трех окнах, которые вы видите на скриншоте выше. Окно настроек Summary зависает через раз. Причем так, что вырубить его можно только отключением процесса в Диспетчере задач, по-другому - никак. А закрыть окно синхронизации можно только путем разлогинивания в системе.

Если нажать на "Нет", окно будет постоянно висеть открытым. При том, что сам браузер, наоборот, время от времени самопроизвольно выключается. И что смешно: браузер выключается, а зависшее окно Summary и открытое окно Синхронизации - нет, так и висят они бесхозные, брошенные браузером, пока не вырубишь их в Диспетчере задач. Фееричные глюки!

Впрочем, не правильно было бы не перечислить и положительные стороны браузера .

Во-первых, это режим анонимного серфинга. Включаете в настройках этот режим и браузер не использует кэш, куки, не записывает историю посещений. Есть браузеры, которые работают только в таком режиме, например, Browzar , что иногда необходимо, но в целом крайне неудобно. И возможность быстрого подключения-отключения такого режима - большой плюс браузеру.

Во-вторых, в YRC Weblink есть возможность выбора поисковой системы по умолчанию. Выбирать, правда, приходится из достаточно специфичного списка:

Однако, адрес поисковой машины можно задать и вручную, нажав на копку Define New (на скриншоте ее не видно, она под списком).

Ну и последний, но очень весомый плюс - YRC Weblink почти не грузит систему ! Для сравнения открыл в нем 10 вкладок и 10 вкладок с теми же самыми адресами открыл в Яндекс-браузере (лидере среди браузеров по загрузке системы) и вот какая картина получилась.

Яндекс-браузер:

Не трудно догадаться, что YRC Weblink в этом смысле практичеси вне конкуренции, в хорошем смысле.


РЕЗЮМЕ . Если бы все задумки, которые создатели пытались внедрить в этом браузере, были сделаны как надо, цены бы ему не было, YRC Weblink мог бы претендовать на звание лучшего или, как минимум, одного из лучших браузеров. Но с теми недоработками, какие в нем наблюдаются, он даже на "троечку" не тянет. Ставлю ему оценку 3- .

После тестирования, браузер деинсталирую - иметь на компьютере столь глючную программу совершенно ни к чему. Ну и ждем дальнейших шагов от YRC Group Inc. Сумеют индийские программисты устранить все недоработки и выпустить действительно рабочую версию браузера, честь им и хвала. Не сумеют - еще одним мертворожденным браузером в мире будет больше.

Слоеный пирог

Речь пойдет о компоненте com_weblinks и о html-разметке страницы Joomla. О том, как легко и просто создать каталог ссылок на сайте Joomla.

Эта CMS и создавалась для интерактивной работы с зарегистрированным пользователем, без прямого кодирования. Хотя тенденция развитя Joomla ведет к тому, чтобы отказаться от компонента com_weblinks вовсе как от бесполезного на сайте, и просто добавляющего лишний вес (более 100 кб - 90 файлов) и без того "тяжелой" системе. Но пока этот компонент еще присутствует в дистрибутиве и используется некоторыми программистами.

Видимая на экране страница сайта Joomla представляет из себя слоеный пирог, в построении которого одновременно участвует много блоков (соответственно много шаблонов). Здесь сказывается философия Joomla - крупноблочное сайтостроение. Для каждого блока обязательно есть свой шаблон (макет) html-разметки.

Основные блоки:

Шаблон главной страницы (шаблон_сайта/index.php), который своей html-разметкой определяет позиции для модулей и компонентов и выводит эти модули и компоненты.
- шаблон страницы
- шаблоны модулей
- шаблоны компонентов

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

Начинающему программисту бывает трудно понять, что первая строка в контентной части страницы выводится как заголовок страницы и редактируется на странице редактирования пункта меню, который указывает на эту страницу. Что вторая строка выводится из шаблона компонента com_content или com_weblinks . А строки в шаблонах как правило - это строковые переменные и их инициализация и локализация производится в языковых файлах, таких как language\ru-RU\ru-RU.mod_weblinks.ini и им подобных.

Иногда начинающего ставит в тупик: какой именно шаблон вывел ту или иную строку, которые на экранной странице выглядят как логичное продолжение одного и того-же повествования. Оказывается одна строка находится в одном шаблоне, другая во втором шаблоне, третья в третьем. А таблица со вкладками, расположенная ниже - это вывод из шаблона модуля mod_tabform.

Иногда шаблоны модулей называют макетами. Но это вопрос терминологии. Суть одна - это "одежда" для содержимого. Правильнее сказать - разметка. Так вот разметка одной экранной страницы находится в разных файлах каталогов Joomla.

Меню

Многие начинающие программисты Joomla часто не понимают, что пункты меню могут иметь разные типы. Иными словами - пункты меню могут ссылаться на объекты Joomla разных типов. Это могут быть разные объекты, такие как: компоненты (голосование, поиск, каталог ссылок и тд).

Выбор типа пункта меню:

Контакты (com_contact )
Список категорий контактов (categories )
Список контактов заданной категории (category )
Контакт (contact )
Избранные контакты (featured )

Материалы (com_content )
Архивные материалы (archive )
Материал (article)
Список всех категорий (categories )
Блог категории (blog category )
Список материалов категории (category)
Избранные материалы (featured )
Создать материал

Умный поиск (com_search )
Поиск (search )

Hello World! (com_helloworld )
Сообщение (helloworld )

Ленты новостей (com_newsfeeds )
Список всех категорий лент новостей (categories )
Список лент новостей в категории (category)
Лента новостей (newsfeed)

Поиск (com_search )
Форма поиска и список результатов поиска (search)

Менеджер пользователей (com_users )
Форма авторизации (login)
Профиль пользователя (profile)
Изменить профиль пользователя
Форма регистрации (registration)
Восстановление имени пользователя (remind)
Изменение пароля (reset)

Обёртка (com_wrapper )
Обёртка (wrapper)

Как видим, здесь все типы меню являются компонентами. Своим названием тип пункта меню фактически указывает на имя шаблона своего типа компонента. А шаблоны компонентов находятся в каталогах views (вид):

joomla\components\com_weblinks \views\categories
joomla\components\com_weblinks \views\category
joomla\components\com_weblinks \views\weblink
joomla\components\com_users\views\login

Как видим имена типов ссылок в меню и имена шаблонов в каталогах vews совпадают.

Разработчик имеет возможность создавать новые нестандартные шаблоны (макеты) для компонентов. Эти новые макеты так же будут отражаться в качестве новых типов меню в окне выбора типов меню. Это отдельная тема.

Демоконтент дистрибутива Joomla

Посмотрим как выстроена иерархия пунктов Меню "About Joomla" для отображения Компонента com_weblinks на установленном по умолчанию демо контенте (шаблон Beez2 - Default) Joomla.

Зайдем в админке на страницу редактирования компонента com_weblinks : Компоненты->Ссылки. Видим, что в демоконтенте, идущем с дистрибутивом создано пять категорий для компонента com_weblinks . Значит ссылки будут распределены по пяти категориям. Все созданные категории будут сохранены в таблице БД #_categories. В этой же таблице сохраняются категории и для других компонентов.

Sample Data-Weblinks
|-Park Links
|-Joomla! Specific Links
|-|-Other Resources
Uncategorised

В меню About Joomla (в редакторе меню) соответственно создана иерархия пунктов меню:

Иерархия пунктов меню:

Using Joomla! (тип: материал)
|-Using Extensions (тип: список всех категорий) :: список категорий в материалах
|-|-Components (тип: блог категории) :: категория в материалах
|-|-|-Weblinks Component (тип: материал)
|-|-|-|-Submit a Weblink (тип: создать ссылку) :: в компоненте Ссылки
|-|-|-|-Weblinks Single Category (тип: список ссылок в категории) :: в компоненте Ссылки
|-|-|-|-Weblinks Categories (тип: список категорий ссылок) :: в компоненте Ссылки

Видим, что некоторые пункты меню имеют типы: список категорий, список ссылок в категории и создать ссылку.
В "Список категорий ссылок" указывается верхняя категория, от которой будет показана иерархия.
В "Список ссылок в категории" указана категория, ссылки которой будут выведены.
В пункте "Создать ссылку" будет будет выведена форма, которую должен будет заполнить зарегистрированный пользователь.
Вот кстати как выглядит в редакторе ссылка на эту форму (в адресной строке ее вид изменится):

index.php?option=com_weblinks&view=form&layout=edit

Некоторые пункты в меню могут быть показаны только зарегистрированному пользователю! Например пункт меню с типом "Создать ссылку" будет виден только для зарегистрированных пользователей. Эта возможность создана специально для того, чтобы зарегистрированные пользователи могли создавать ссылки, которые будут размещены на странице.

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

Возможность пользователю самому добавлять ссылки на внешние сайты - это основной плюс и смысл компонента com_weblinks , как и возможность добавления пользователем нового контента - статей, изображений, видео файлов и тд.

Дать возможность зарегистрированному пользователю, наделенному правами, наполнять сайт содержимым без прямого кодирования - основная философия CMS Joomla.

Uncategorised
Sample Data-Articles
|- Joomla!
|-|- Extensions
|-|-|- Components
|-|-|- Modules
|-|-|-|- Content Modules
|-|-|-|- User Modules
|-|-|-|- Display Modules
|-|-|-|- Utility Modules
|-|-|-|- Navigation Modules
|-|-|- Templates
|-|-|-|- Atomic
|-|-|-|- Beez 20
|-|-|-|- Beez 5
|-|-|- Languages
|-|-|- Plugins
|- Park Site
|-|- Park Blog
|-|- Photo Gallery
|-|-|- Animals
|-|-|- Scenery
|- Fruit Shop Site
|-|- Growers
|-|- Recipes

Кажется не слишком много категорий для материалов!
Посмотреть иерархию категорий в материалах можно так же при помощи запроса к таблице категорий в БД:

SELECT * FROM `#_categories` WHERE `extension` = "com_content"

В текущем месяце багокопатели не хотят нас баловать новыми громкими эксплойтами в популярных приложениях. Конечно, опубликовано множество advisory в продуктах известных фирм, но очень малое их количество содержит удобоваримые PoC-коды. В нашем обзоре я постарался собрать самые значимые и полные уязвимости из описанных в последнее время, так что устраивайся поудобнее и наслаждайся чтением.

Уязвимость PHP при обработке HTTP Head-запросов Brief

3 марта некий Адам Иванюк обнаружил интересную особенность в интерпретаторе PHP, который не совсем корректно обрабатывает HEAD-запросы. Данную уязвимость исследователь назвал «HTTP HEAD method trick in php scripts».

Многие кодеры разрабатывают свои PHP-скрипты, надеясь, что все записанные в них инструкции успешно выполнятся, не прервавшись где-нибудь посередине (особенно в коротких скриптах). Так и происходит, если скрипт запрашивается конечным пользователем с помощью методов GET, POST, PUT.

Но тебе должно быть известно, что существуют и другие HTTP-методы - например, HEAD. Как раз-таки при обработке этого метода в PHP и может возникнуть дыра в безопасности.

Смотрим один из исходников интерпретатора: ./main/SAPI.c, линия 315:

if (SG(request_info).request_method &&
!strcmp(SG(request_info).request_method, "HEAD"))
{
SG(request_info).headers_only = 1;
...

Когда поступают какие-либо данные, выполняется функция php_ub_body_write. Дальше смотрим main/output.c, линия 699:

if (SG(request_info).headers_only) {
if(SG(headers_sent))
{
return 0;
}
php_header(TSRMLS_C);
zend_bailout();
}

Здесь видно, что при первом выводе на экран и при использовании метода HEAD функция zend_bailout прерывает работу скрипта.

Exploit

Теперь давай обратимся к этому скрипту с помощью метода HEAD:

Как и следовало ожидать, наша гостевая книга остановит свое выполнение на строчке «echo $data;», таким образом файл book.txt просто-напросто обнулится.
Данный пример носит скорее деструктивный характер. Во втором примере мы сможем обойти авторизацию в примитивной админке:

В этом скрипте при заходе обычными методами устанавливается административная переменная в сессии. Затем, если пользователь ввел неправильный пароль, эта переменная обнуляется и пользователь не становится админом.

Если мы обратимся к админке через HEAD, ее выполнение прервется на куске кода с «echo», таким образом административная переменная не обнулится, и мы сможем спокойно бродить по закрытой части приложения. Здесь надо учесть, что в большинстве веб-серверов значение буферизации вывода установлено равным 4096 байт, так что в рабочем примере нам может понадобиться строка ‘A long string contains about 4090 characters’.

Exploit
  • PHP

    Здесь массив $check содержит наши POST-данные, а переменная $locked - это обфусцированная с помощью функции str_rot13() сериализованная строка, которая полностью находится под нашим контролем.

    На этом месте стоит сделать небольшое отступление для тех, кто не читал соответствующие статьи в ][, и кратко рассказать о баге, проявляющемся в волшебных методах PHP. Итак, в PHP версии 5 появилась базовая концепция ООПпрограммирования: конструктор и деструктор. Конструктор реализуется с помощью метода «__construct», а деструктор - с помощью метода «__destruct». По окончании своей работы и при вызове через функцию unserialize() каждый объект выполняет свой собственный __ destruct-метод, если он прописан в коде.

    Теперь вернемся к нашему фреймворку и посмотрим на деструктор App-класса из файла./libs/configure.php:

    function __destruct()
    {
    if ($this->__cache)
    {
    $core = App::core("cake");
    unset($this->__paths);
    Cache::write("dir_map", array_fi lter($this->__paths),
    "cake_core ");
    Cache::write("fi le_map", array_fi lter($this->__map),
    "cake_core ");
    Cache::write("object_map", $this->__objects,
    "cake_core ");
    }
    }

    Из приведенного кода можно понять, что данный метод может быть скомпрометирован путем записи произвольных значений в объект Cache. Наиболее интересный ключ для взлома - это ‘file_map’. Он управляет связями между классами и соответствующими PHP-файлами, а также используется для подгрузки дополнительных классов во время выполнения скрипта.

    Реальный код для загрузки классов выглядит немного сложнее, но все это сводится к следующему коду из метода __load внутри класса App:

    Бинго! Путем подмены переменной $file мы сможем проинклудить свой собственный PHP-код! Причем это будет самый настоящий Remote File Inclusion баг - таким образом, нам не понадобятся никакие дополнительные ухищрения с загрузкой локальных файлов на сервер. Однако автор найденной уязвимости предлагает LFI-вариант эксплуатации этой дырки, потому что CakePHP использует базирующийся на файлах локальный кэш, который находится в сериализированной форме в известной взломщику директории.

    Exploit

    В качестве небольшого PoC для генерации ядовитой сериализованной строки felix предлагает следующий код:

    Конечно, предварительно ты должен проинклудить необходимые классы из CakePHP. Существует также и полнофункциональный эксплойт на Питоне, найти который ты сможешь по адресу malloc.im/burnedcake.py .

    Данный сплойт должен работать в каждом приложении, построенном на CakePHP, использующем POST-формы с security-токенами, и в котором не изменено стандартное расположение файлов кэша. По дефолту эксплойт выводит на экран конфиг базы данных, другие полезности легко добавляются путем измененения встроенного PHP-пэйлоада.

    Targets
    • CakePHP getState("fi lter_order_dir");
      $fi lter_order = JFilterInput::clean($fi lter_order, "cmd");
      $fi lter_order_dir =
      JFilterInput::clean($fi lter_order_dir, "word");
      // We need to get a list of all
      // weblinks in the given category
      $query = "SELECT *" .
      " FROM #__weblinks" .
      " WHERE catid = ". (int) $this->_id.
      " AND published = 1" .
      " AND archived = 0".
      " ORDER BY ". $fi lter_order ."".
      $fi lter_order_dir .", ordering";
      return $query;
      }

      Здесь видно, что переменные $filter_order и $filter_order_dir не проходят проверку на строгое соответствие операторам SQL, проверка идет лишь путем использования стандартного метода clean из класса JFilterInput: