Share
## https://sploitus.com/exploit?id=D0D2BEBC-92CA-5CE2-87A6-E7A2ACAFC53B
```
     โ–„โ–„                 โ–„โ–„                
   โ–„โ–ˆโ–€โ–€โ–ˆโ–„   โ–ˆโ–„  โ–ˆโ–„       โ–ˆโ–ˆ               
   โ–ˆโ–ˆ  โ–ˆโ–ˆ  โ–„โ–ˆโ–ˆโ–„โ–„โ–ˆโ–ˆโ–„      โ–ˆโ–ˆ โ–€โ–€       โ–„    
   โ–ˆโ–ˆโ–€โ–€โ–ˆโ–ˆ   โ–ˆโ–ˆ  โ–ˆโ–ˆ โ–„โ–ˆโ–€โ–ˆโ–„ โ–ˆโ–ˆ โ–ˆโ–ˆ โ–„โ–ˆโ–€โ–ˆโ–„ โ–ˆโ–ˆโ–ˆโ–ˆโ–„
 โ–„ โ–ˆโ–ˆ  โ–ˆโ–ˆ   โ–ˆโ–ˆ  โ–ˆโ–ˆ โ–ˆโ–ˆโ–„โ–ˆโ–€ โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆโ–„โ–ˆโ–€ โ–ˆโ–ˆ   
 โ–€โ–ˆโ–ˆโ–€  โ–€โ–ˆโ–„โ–ˆโ–„โ–ˆโ–ˆ โ–„โ–ˆโ–ˆโ–„โ–€โ–ˆโ–„โ–„โ–„โ–„โ–ˆโ–ˆโ–„โ–ˆโ–ˆโ–„โ–€โ–ˆโ–„โ–„โ–„โ–„โ–ˆโ–€   
                                          
โ‰ปโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ‹†โœฉโ‹† โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ‰บ

CVE-2025-53328

Developed by @XoanOuteiro 
At https://github.com/attelier

โ‰ปโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ‹†โœฉโ‹† โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ‰บ
```

# CVE-2025-53328 โ€” Unauthenticated Local File Inclusion in Opinion Stage

## Overview

| Field              | Value                                                                              |
|--------------------|------------------------------------------------------------------------------------|
| CVE                | CVE-2025-53328                                                                     |
| Plugin             | social-polls-by-opinionstage (Opinion Stage Poll, Survey & Quiz Maker)             |
| Vulnerable version | โ‰ค 19.11.0                                                                          |
| Patched in         | 19.11.1                                                                            |
| Type               | Local File Inclusion (Unauthenticated) โ€” CWE-98                                   |
| CVSS               | 7.5โ€“8.1 (High)                                                                     |
| Original reporter  | Ananda Dhakal (Patchstack)                                                         |
| CVE published      | 26 Aug 2025                                                                        |

The Opinion Stage plugin for WordPress (โ‰ค 19.11.0) contains an unauthenticated Local File Inclusion vulnerability in `admin/admin-page-loader.php`. A `$_REQUEST` parameter is passed through `sanitize_text_field()` โ€” which does not filter path traversal sequences โ€” and used to construct a path for `include_once`. The vulnerable code is reachable without authentication via `admin-ajax.php` or `admin-post.php`.

---

## Vulnerable file identification

Diffing version 19.8.20 against 19.11.1:

```bash
diff -rq social-polls-by-opinionstage/ patched/social-polls-by-opinionstage/
```

The patch removes `admin/admin-page-loader.php` entirely, along with `admin/resources/` and `admin/helpers/`. The admin page-loading architecture was replaced by `src/Modules/Admin.php`.

---

## Source analysis

### Sink โ€” `OpinionStageAdminPageLoader` class in `admin/admin-page-loader.php`

**Parameter ingestion** (`prepare_slug()`):

```
Line 71:  if ( ! empty( $_REQUEST['page'] ) ) {
Line 72:      $qry_str_check_os = sanitize_text_field( $_REQUEST['page'] );
Line 75:          $this->slug = str_replace( 'opinionstage-', '', sanitize_text_field( $_REQUEST['page'] ) );
```

The method reads `$_REQUEST['page']`, verifies that it contains the `opinionstage-` prefix, strips the prefix, and stores the remainder as `$this->slug`. The only sanitization applied is `sanitize_text_field()`, which strips HTML tags and normalizes whitespace but does not filter directory traversal characters.

**File inclusion** (`load_file()`):

```php
include_once plugin_dir_path(__FILE__) . 'resources/' . $this->slug . '.php';
```

**Secondary inclusion** (`maybe_load_template_file()`):

Includes from `helpers/` and `views/` using the same unsanitized slug.

**Tertiary vector** (`load_assets()`):

```php
call_user_func('opinionstage_' . $slug . '_load_resources');
```

Dynamic function call constructed from the unsanitized slug.

### Loading chain

```
plugin.php
  โ””โ”€ if (is_admin()) โ†’ require 'admin/init.php'
       โ””โ”€ admin/init.php (line 13) โ†’ require 'admin-page-loader.php'
            โ””โ”€ admin-page-loader.php (line 185) โ†’ OpinionStageAdminPageLoader::get_instance()
                 โ””โ”€ constructor โ†’ prepare_slug() โ†’ load_file() โ†’ include_once
```

The class is instantiated via `get_instance()` at file scope. The constructor calls `prepare_slug()` and `load_file()` immediately โ€” before WordPress performs any authentication or capability check.

### Why it's unauthenticated

`is_admin()` returns `true` for any request to a URL under `/wp-admin/`, regardless of authentication status. It checks the request path, not the user session. Endpoints such as `admin-ajax.php` and `admin-post.php` reside under `/wp-admin/` and are accessible without authentication.

The include fires during plugin initialization, before WordPress reaches any `check_ajax_referer()`, `current_user_can()`, or session validation.

---

## Endpoint

```
GET /wp-admin/admin-ajax.php?page=opinionstage-
GET /wp-admin/admin-post.php?page=opinionstage-
```

Both endpoints are accessible without authentication. The `page` parameter is processed during plugin load.

---

## Include path

The base path resolved by `plugin_dir_path(__FILE__) . 'resources/'` is:

```
/var/www/html/wp-content/plugins/social-polls-by-opinionstage/admin/resources/
```

The `.php` extension is appended automatically. A traversal payload of `../../../../../wp-config` resolves to:

```
/var/www/html/wp-content/plugins/social-polls-by-opinionstage/admin/resources/../../../../../wp-config.php
โ†’ /var/www/html/wp-config.php
```

The depth of traversal required depends on the WordPress installation layout.

---

## Exploitation constraints

### .php extension lock

`load_file()` appends `.php` unconditionally. Only files with a `.php` extension can be included. Null byte termination (`%00`) to truncate the extension is not viable on PHP โ‰ฅ 5.3.4.

### PHP wrapper blockage

The mandatory `opinionstage-` prefix prevents the use of PHP stream wrappers. The `$_REQUEST['page']` value must contain `opinionstage-` to pass the prefix check โ€” there is no way to begin the value with `php://`, `data://`, `expect://`, or any other wrapper scheme while satisfying this constraint.

### Include executes, does not display

Included `.php` files are executed by the PHP interpreter. Their source code is not returned in the response. Including `wp-config.php` causes its `define()` calls to execute silently โ€” database credentials are loaded into memory but produce no output visible to the attacker.

### No standard .php log files

Log poisoning would require a log file with a `.php` extension, which is not a standard configuration in Apache, Nginx, or any common WordPress deployment.

---

## Chaining potential โ€” LFI to RCE

While standalone impact on a clean install is limited, this vulnerability becomes a reliable **unauthenticated RCE primitive** when chained with any condition that places attacker-controlled `.php` content on the filesystem.

### Chain: Arbitrary File Upload + LFI

If an attacker can upload a `.php` file to any known path on the target โ€” via a separate vulnerability in another plugin, theme, or WordPress core โ€” this LFI can include and execute it.

This chain is particularly effective because:

- Arbitrary file upload vulnerabilities in WordPress plugins are common. Multiple critical AFU CVEs are disclosed monthly across the ecosystem.
- Many AFU vulnerabilities write files to predictable paths (e.g., `wp-content/uploads/YYYY/MM/filename.php`).
- Server-side defenses against uploaded PHP execution (`.htaccess` rules denying direct PHP execution in `uploads/`, Nginx `location` blocks) are **completely bypassed**. The inclusion happens from the plugin's own process context, not from a direct HTTP request to the uploaded file. The web server never needs to route a request to the uploaded path.

### Chain: Any writable .php on disk

The AFU case is the most common, but any scenario that results in attacker-controlled `.php` content on the filesystem produces the same chain:

- SQL injection with `SELECT INTO OUTFILE` writing to a path within traversal range.
- A plugin that stores user-supplied content in `.php` files (cache engines, configuration generators, compiled template caches).
- Race conditions in temporary file creation where a `.php` temp file exists at a predictable path for a window of time.
- A previously compromised upload directory where a webshell was placed but is not directly accessible due to execution restrictions.

### Impact when chained

The combined result is **unauthenticated remote code execution** running as the web server user (`www-data`, `apache`, `nginx`). No direct URL access to the uploaded file is required, no authentication is needed, and no user interaction is involved.

---

## Standalone impact assessment

On a clean WordPress install with no other vulnerabilities present, the LFI can include arbitrary `.php` files from the local filesystem but cannot:

- Read their source code (executed, not displayed).
- Include non-PHP files (extension is forced).
- Use PHP wrappers to transform output (prefix blocks wrapper schemes).

Existing WordPress `.php` files that could be included (e.g., `wp-config.php`, core files) do not produce exploitable output when re-included in this context.

**Standalone severity: Low.**
**Chained severity: Critical (unauthenticated RCE).**

---

## Fix

Version 19.11.1 removes `admin/admin-page-loader.php` and the associated `resources/` and `helpers/` directories entirely. The admin page routing was rewritten in `src/Modules/Admin.php` using WordPress's `add_menu_page()` / `add_submenu_page()` API with proper callback registration, eliminating the dynamic include pattern.

---

## References

- [Patchstack CVE-2025-53328](https://patchstack.com/database/vulnerability/social-polls-by-opinionstage/)
- [SolidWP vulnerability report โ€” September 3, 2025](https://solidwp.com/blog/wordpress-vulnerability-report-september-3-2025/)
- [WordPress Plugin Directory โ€” social-polls-by-opinionstage](https://wordpress.org/plugins/social-polls-by-opinionstage/)