Уязвим ли wp-cron.php для внешних атак и как его защитить?

29 янв. 2015 г., 21:33:02
Просмотры: 43.2K
Голосов: 13

Я использую WordPress v.4.1, все плагины и тема обновлены до последних версий.

Я вижу в моих лог-файлах слишком много таких записей...

xxx.xxx.xxx.xxx - - [02/Jan/2015:13:30:27 +0200] "POST /wp-cron.php?doing_wp_cron=1420198227.5184459686279296875000 HTTP/1.0" 200 - "-" "WordPress/217; http://www.example.com"

где xxx.xxx.xxx.xxx - это IP-адрес сервера, на котором размещен сайт, а "http://www.example.com" - это мой веб-сайт.

Существует ли известная уязвимость (эксплойт), затрагивающая wp-cron.php?
Есть ли способ "защитить" этот файл?

Спасибо!

0
Все ответы на вопрос 2
0

В файле wp-includes/default-filters.php можно найти регистрацию callback-функции:

// WP Cron
if ( !defined( 'DOING_CRON' ) )
    add_action( 'init', 'wp_cron' );

Если теперь перейти к функции wp_cron(), мы увидим следующее:

$schedules = wp_get_schedules();
foreach ( $crons as $timestamp => $cronhooks ) {
    if ( $timestamp > $gmt_time ) break;
    foreach ( (array) $cronhooks as $hook => $args ) {
        if ( isset($schedules[$hook]['callback']) && !call_user_func( $schedules[$hook]['callback'] ) )
            continue;
        spawn_cron( $gmt_time );
        break 2;
    }
}

Функция spawn_cron() отправляет POST-запрос, который вы видите в своих логах:

$doing_wp_cron = sprintf( '%.22F', $gmt_time );
set_transient( 'doing_cron', $doing_wp_cron );

/**
 * Фильтр аргументов запроса cron.
 *
 * @since 3.5.0
 *
 * @param array $cron_request_array {
 *     Массив аргументов URL запроса cron.
 *
 *     @type string $url  URL запроса cron.
 *     @type int    $key  22-значное время в микросекундах по GMT.
 *     @type array  $args {
 *         Массив аргументов запроса cron.
 *
 *         @type int  $timeout   Таймаут запроса в секундах. По умолчанию .01 секунды.
 *         @type bool $blocking  Блокирующий ли запрос. По умолчанию false.
 *         @type bool $sslverify Проверять ли SSL для запроса. По умолчанию false.
 *     }
 * }
 */
$cron_request = apply_filters( 'cron_request', array(
    'url'  => add_query_arg( 'doing_wp_cron', $doing_wp_cron, site_url( 'wp-cron.php' ) ),
    'key'  => $doing_wp_cron,
    'args' => array(
        'timeout'   => 0.01,
        'blocking'  => false,
        /** Этот фильтр документирован в wp-includes/class-http.php */
        'sslverify' => apply_filters( 'https_local_ssl_verify', false )
    )
) );

wp_remote_post( $cron_request['url'], $cron_request['args'] );

Здесь также видно, откуда берется число с плавающей точкой: оно передается как аргумент для идентификации транзиента.

Беспокоиться не о чем.

29 янв. 2015 г. 22:24:18
6

Если вы хотите защитить файл, можно ограничить доступ к нему через ваш httpd.conf (глобальный конфигурационный файл Apache).

# Файл wp-cron.php WordPress
<Files "wp-cron.php">
  Require ip 1.2.3.4
</Files>

Замените IP в примере на IP вашего сервера. Это позволит вам по-прежнему получать доступ к файлу с сервера, используя команду, например:

wget -q -O - domain.com/wp-cron.php?doing_wp_cron

И будет возвращаться ошибка 403 (доступ запрещён для запросов с любых других IP). Если вы используете дополнительное правило, как показано ниже, вы можете перенаправлять внешние запросы с 403 Forbidden на другую страницу (например, на главную), что не является обязательным.

ErrorDocument 403 https://www.domain.ca

Ещё лучше использовать Require ip 127.0.0.1 в примере выше и запрос wget: wget -q -O - 127.0.0.1/wp-cron.php?doing_wp_cron. Это задействует loopback-интерфейс, и ваш запрос не будет перенаправляться в публичный интернет и обратно.

6 июн. 2019 г. 17:56:50
Комментарии

который будет блокировать вызовы из cron ОС, обычно выполняемые с помощью wget

Mark Kaplun Mark Kaplun
6 июн. 2019 г. 19:17:03

Можете указать, где в исходном коде вызывается wget? Быстрый поиск не помог мне быстро найти это. Я нашел несколько упоминаний wget, но только в плагинах WordFence и BulletProof.

I'm Root James I'm Root James
6 июн. 2019 г. 21:36:07

WordPress не использует cron ОС. Также, используя указанное выше правило, я смог выполнить wget wp-cron.php, используя как wget http://localhost/wp-cron.php, так и wget http://127.0.0.1/wp-cron.php. Однако при попытке доступа извне я вижу следующее в access_log: "GET /wp-cron.php HTTP/1.1" 302 (перенаправление). Потому что у меня также есть ErrorDocument 403 https://www.domain.com/index.php, который перенаправляет все запрещенные запросы на главную страницу.

I'm Root James I'm Root James
6 июн. 2019 г. 21:45:16

cron в WordPress вызывается через HTTP-запросы из ядра системы. Все руководства в интернете рекомендуют использовать wget для запуска WP cron из системного cron в качестве замены нативного механизма WordPress. Кроме того, фильтрация по IP-адресу, которая всегда является проигрышной стратегией, в данном случае еще хуже — при переносе сайта cron либо перестанет работать без очевидной причины, либо эти правила просто потеряют всякий смысл.

Mark Kaplun Mark Kaplun
7 июн. 2019 г. 19:20:41

В таком случае используйте 127.0.0.1 вместо публичного IP-адреса сервера, как я упомянул в своем ответе.

I'm Root James I'm Root James
7 июн. 2019 г. 22:13:05

WordPress никогда не использует wget для WP-Cron, и если вы настраиваете задания cron на уровне ОС, вам, вероятно, также не следует использовать wget. Этот ответ умный, но недостаточно полный... вы могли бы ограничить доступ к wp-cron.php, но затем использовать либо WP-CLI, либо /usr/bin/php для его локального вызова.

Jesse Nickles Jesse Nickles
15 мар. 2023 г. 12:41:47
Показать остальные 1 комментариев