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

Баг был обнаружен еще 20 ноября 2017 года исследователем Славко Михайльоски (Slavco Mihajloski) из RIPS Tech, но вплоть до версии 4.9.7, которая вышла 5 июня 2018 года, проблема оставалась незапатченной. То есть на протяжении семи месяцев она представляла серьезную угрозу для безопасности на огромном количестве сайтов по всему миру и на многих из них продолжает представлять.

 

Стенд

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

$ docker run -d --rm -e MYSQL_USER="wpdel" -e MYSQL_PASSWORD="4hicmMRyUq" -e MYSQL_DATABASE="wpdel" --name=mysql --hostname=mysql mysql/mysql-server

Теперь контейнер, на который поставим веб-сервер. На нем будет располагаться WordPress.

$ docker run -it --rm -p80:80 --name=wpdel --hostname=wpdel --link=mysql debian /bin/bash

Установим все нужные пакеты и расширения PHP.

$ apt-get update && apt-get install -y apache2 php php7.0-mysqli php-gd nano wget

Уязвима версия CMS под номером 4.9.6, ее и скачаем.

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

Запускаем сервис apache2.

$ service apache2 start

Теперь устанавливаем WordPress, используем наш MySQL-сервер в качестве БД.

Инсталляция WordPress 4.9.6
Инсталляция WordPress 4.9.6

Уязвим механизм удаления загруженных файлов, поэтому для успешной эксплуатации юзер должен иметь привилегии на удаление медиа. Создадим такого пользователя.

Создание пользователя с привилегиями добавления медиафайлов в WordPress 4.9.6
Создание пользователя с привилегиями добавления медиафайлов в WordPress 4.9.6
 

Анализ уязвимости

В WordPress, как и в любой уважающей себя CMS, можно загружать произвольные файлы и встраивать их в публикуемые посты. Самый очевидный способ применения — это добавление фотографий. Если файл загруженной картинки больше установленных в настройках размеров, то для него создаются миниатюры (thumbnails). Самую мелкую из них можно увидеть при нажатии на кнопку редактирования картинки (в закладке медиа в разделе Thumbnail Settings).

Редактирование загруженной картинки в WordPress
Редактирование загруженной картинки в WordPress

Заглянем в файл post.php, где находится кусок кода, ответственный за редактирование любой записи в системе. Да, аттачи тоже считаются записями.

/wordpress/wp-admin/post.php
33: if ( $post_id )
34:     $post = get_post( $post_id );
...
62: switch($action) {

В переменной $action находится действие из запроса, которое нужно выполнить. Оператор switch перенаправляет выполнение скрипта в нужную часть кода. Вот, к примеру, запрос на редактирование конкретной записи.

GET /wp-admin/post.php?post=25&action=edit HTTP/1.1
Host: wpdel.visualhack
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7,bg;q=0.6,uk;q=0.5,hu;q=0.4

При его обработке исполняется следующий кусок кода:

062: switch($action) {
...
098: case 'edit':
099:    $editing = true;
...
122:    if ( ! empty( $_GET['get-post-lock'] ) ) {
123:        check_admin_referer( 'lock-post_' . $post_id );
124:        wp_set_post_lock( $post_id );
125:        wp_redirect( get_edit_post_link( $post_id, 'url' ) );
126:        exit();
127:    }
128:
129:    $post_type = $post->post_type;
130:    if ( 'post' == $post_type ) {
131:        $parent_file = "edit.php";
132:        $submenu_file = "edit.php";
133:        $post_new_file = "post-new.php";
134:    } elseif ( 'attachment' == $post_type ) {
135:        $parent_file = 'upload.php';
136:        $submenu_file = 'upload.php';
137:        $post_new_file = 'media-new.php';
138:    } else {
139:        if ( isset( $post_type_object ) && $post_type_object->show_in_menu && $post_type_object->show_in_menu !== true )
140:            $parent_file = $post_type_object->show_in_menu;
141:        else
142:            $parent_file = "edit.php?post_type=$post_type";
143:        $submenu_file = "edit.php?post_type=$post_type";
144:        $post_new_file = "post-new.php?post_type=$post_type";
145:    }
146:
...
174:    include( ABSPATH . 'wp-admin/edit-form-advanced.php' );
175:
176:    break;

Погуляв немного по этой ветке кода, можно обнаружить довольно любопытный экшен.

178: case 'editattachment':
179:    check_admin_referer('update-post_' . $post_id);
180:
181:    // Don’t let these be changed
182:    unset($_POST['guid']);
183:    $_POST['post_type'] = 'attachment';
184:
185:    // Update the thumbnail filename
186:    $newmeta = wp_get_attachment_metadata( $post_id, true );
187:    $newmeta['thumb'] = $_POST['thumb'];
188:
189:    wp_update_attachment_metadata( $post_id, $newmeta );

Особенно интересен раздел Update the thumbnail filename. Переменная $newmeta содержит метаданные записи с указанным ID. Ключ thumb содержит путь до миниатюры, и его значение можно изменить с помощью параметра thumb в POST-запросе. Эти данные уходят в функцию wp_update_attachment_metadata, которая расположилась чуть ниже в этом же файле.

Продолжение доступно только подписчикам

Материалы из последних выпусков можно покупать отдельно только через два месяца после публикации. Чтобы продолжить чтение, необходимо купить подписку.

Подпишись на «Хакер» по выгодной цене!

Подписка позволит тебе в течение указанного срока читать ВСЕ платные материалы сайта. Мы принимаем оплату банковскими картами, электронными деньгами и переводами со счетов мобильных операторов. Подробнее о подписке

Оставить мнение

Check Also

Миллионы Android-приложений уязвимы перед проблемой Man-in-the-Disk

Эксперты Check Point описали новый вектор атак на Android-устройства — Man-in-the-Disk (Mi…