Il file wp-cron.php di WordPress è vulnerabile ad attacchi esterni e come proteggerlo?
Sto utilizzando WordPress v.4.1 e tutti i plugin e il tema sono aggiornati.
Nei miei file di log vedo molte di queste righe...
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"
dove xxx.xxx.xxx.xxx è l'indirizzo IP del server che ospita il sito web e "http://www.example.com" è il mio sito web.
Esiste una vulnerabilità nota (exploit) che interessa wp-cron.php?
C'è un modo per "proteggere" il file?
Grazie!
Nel file wp-includes/default-filters.php
possiamo trovare la registrazione di un callback:
// WP Cron
if ( !defined( 'DOING_CRON' ) )
add_action( 'init', 'wp_cron' );
Se ora andiamo alla funzione wp_cron()
, vediamo questo:
$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()
invia la richiesta POST che stai vedendo nei tuoi log:
$doing_wp_cron = sprintf( '%.22F', $gmt_time );
set_transient( 'doing_cron', $doing_wp_cron );
/**
* Filtra gli argomenti della richiesta cron.
*
* @since 3.5.0
*
* @param array $cron_request_array {
* Un array di argomenti URL per la richiesta cron.
*
* @type string $url L'URL della richiesta cron.
* @type int $key Il microtime GMT a 22 cifre.
* @type array $args {
* Un array di argomenti per la richiesta cron.
*
* @type int $timeout Il timeout della richiesta in secondi. Default .01 secondi.
* @type bool $blocking Se impostare il blocking per la richiesta. Default false.
* @type bool $sslverify Se verificare SSL per la richiesta. Default 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,
/** Questo filtro è documentato in wp-includes/class-http.php */
'sslverify' => apply_filters( 'https_local_ssl_verify', false )
)
) );
wp_remote_post( $cron_request['url'], $cron_request['args'] );
Qui puoi anche vedere da dove proviene il numero float: viene passato come argomento per identificare il transient.
Niente di cui preoccuparsi.

Se vuoi proteggere il file puoi limitare l'accesso al file tramite il tuo file httpd.conf (file di configurazione globale di Apache).
# File wp-cron.php di Wordpress
<Files "wp-cron.php">
Require ip 1.2.3.4
</Files>
Sostituisci l'IP nell'esempio con l'IP del tuo server. Questo ti consentirà comunque di accedere al file dal server utilizzando un comando come:
wget -q -O - domain.com/wp-cron.php?doing_wp_cron
E restituirà un 403 (accesso negato alle richieste da qualsiasi altro IP). Se usi una regola aggiuntiva come quella qui sotto, reindirizzerai le richieste esterne da 403 Forbidden
a un'altra pagina (come la homepage), cosa che non è strettamente necessaria.
ErrorDocument 403 https://www.domain.ca
Ancora meglio, puoi usare Require ip 127.0.0.1
con l'esempio sopra e usare la richiesta wget: wget -q -O - 127.0.0.1/wp-cron.php?doing_wp_cron
. Questo utilizzerà il controller di rete loopback e la tua richiesta non verrà inoltrata nella rete internet pubblica e ritorno.

che bloccherà le invocazioni dal cron del sistema operativo che di solito vengono eseguite utilizzando wget

Puoi indicarmi dove viene chiamato wget nel codice sorgente? Una ricerca rapida non mi ha aiutato a trovarlo velocemente. Ho trovato diversi riferimenti a wget, ma solo nei plugin WordFence e BulletProof.

WordPress non utilizza cron del sistema operativo. Inoltre, usando la regola sopra, sono riuscito a eseguire wget wp-cron.php sia con wget http://localhost/wp-cron.php che con wget http://127.0.0.1/wp-cron.php. Tuttavia, quando ho tentato di accedere dall'esterno ho ottenuto quanto segue nell'access_log "GET /wp-cron.php HTTP/1.1" 302 (reindirizzamento). Questo perché ho anche un ErrorDocument 403 https://www.domain.com/index.php che indirizza tutti gli accessi negati alla homepage.

cron viene richiesto via HTTP dal core di WordPress. Tutti i tutorial disponibili online suggeriscono di usare wget per attivare WP cron dal cron del sistema operativo come sostituto del trigger nativo di WP cron. Inoltre filtrare per IP, che è sempre una strategia perdente, è ancora peggio in questo caso perché quando sposti il sito, o il cron smetterà di funzionare e non saprai perché, o quelle righe smetteranno di avere alcun effetto

Usa 127.0.0.1 invece dell'IP pubblico del server come ho menzionato nella mia risposta allora.

WordPress non usa mai wget
per WP-Cron e se scegli di configurare job cron a livello di sistema operativo, probabilmente non dovresti usare neanche wget
. Questa risposta è intelligente, ma non va abbastanza lontano... potresti limitare l'accesso a wp-cron.php
ma poi usare WP-CLI o /usr/bin/php
per chiamarlo localmente.
