CVE-2026-40754

Roisin - Flower Shop and Florist WordPress Theme <= 1.4 - Unauthenticated PHP Object Injection

highDeserialization of Untrusted Data
8.1
CVSS Score
8.1
CVSS Score
high
Severity
1.5
Patched in
11d
Time to patch

Description

The Roisin - Flower Shop and Florist WordPress Theme theme for WordPress is vulnerable to PHP Object Injection in versions up to, and including, 1.4 via deserialization of untrusted input. This makes it possible for unauthenticated attackers to inject a PHP Object. No known POP chain is present in the vulnerable software. If a POP chain is present via an additional plugin or theme installed on the target system, it could allow the attacker to delete arbitrary files, retrieve sensitive data, or execute code.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
High
Privileges Required
None
User Interaction
None
Scope
Unchanged
High
Confidentiality
High
Integrity
High
Availability

Technical Details

Affected versions<=1.4
PublishedApril 20, 2026
Last updatedApril 30, 2026
Affected themeroisin

Source Code

WordPress.org SVN
Vulnerable v1.4
Patched v1.5
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-40754 (Roisin Theme PHP Object Injection) ## 1. Vulnerability Summary The **Roisin** WordPress theme (up to version 1.4) is vulnerable to **Unauthenticated PHP Object Injection**. This occurs because the theme's backend logic improperly handles user-provided d…

Show full research plan

Exploitation Research Plan: CVE-2026-40754 (Roisin Theme PHP Object Injection)

1. Vulnerability Summary

The Roisin WordPress theme (up to version 1.4) is vulnerable to Unauthenticated PHP Object Injection. This occurs because the theme's backend logic improperly handles user-provided data by passing it through the unserialize() function without prior validation or sanitization. Specifically, the vulnerability is likely located in an AJAX handler used for dynamic layout loading (like sidebars or post pagination), where state information is passed as a base64-encoded, serialized string in a POST parameter.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: roisin_elated_get_sidebar or roisin_elated_load_more (inferred based on Elated theme framework conventions).
  • Vulnerable Parameter: options or query_obj (inferred).
  • Authentication: None required (target is a wp_ajax_nopriv_* hook).
  • Preconditions: The theme must be active. A valid AJAX nonce may be required depending on whether the theme developers implemented check_ajax_referer.

3. Code Flow

  1. Entry Point: An unauthenticated user sends a POST request to admin-ajax.php with a specific action parameter (e.g., roisin_elated_get_sidebar).
  2. Hook Registration: The theme registers the action via:
    add_action('wp_ajax_nopriv_roisin_elated_get_sidebar', 'roisin_elated_get_sidebar_ajax_handler');
  3. Data Retrieval: The handler function (e.g., roisin_elated_get_sidebar_ajax_handler) retrieves a POST parameter:
    $options_encoded = $_POST['options'];
  4. The Sink: The retrieved data is decoded and deserialized:
    $options = unserialize(base64_decode($options_encoded));
  5. Injection: By providing a crafted base64 string, an attacker can inject arbitrary PHP objects into the application scope.

4. Nonce Acquisition Strategy

Elated-Themes typically expose AJAX nonces through a localized JavaScript object available on most public-facing pages.

  1. Identify Shortcode/Page: Any page using the theme's layout (including the homepage) likely enqueues the necessary scripts.
  2. Creation of Test Page:
    wp post create --post_type=page --post_status=publish --post_title="Exploit Prep" --post_content="Testing Roisin"
    
  3. Browser Extraction:
    • Navigate to the homepage or the newly created page.
    • Use browser_eval to extract the nonce from the localized variable.
    • Likely Variable: roisinElatedVars.ajax_nonce or eltdfGlobalVars.vars.admin_ajax_nonce.
    • Execution: browser_eval("window.roisinElatedVars?.ajax_nonce || window.eltdfGlobalVars?.vars?.admin_ajax_nonce")

5. Exploitation Strategy

Since the description states "No known POP chain is present in the vulnerable software," the goal of the PoC is to demonstrate the Object Injection by triggering an observable side effect (e.g., an error or an interaction with a standard WP class).

Step-by-Step Plan:

  1. Search for Sink:
    Confirm the exact action and parameter name by searching the theme directory:
    grep -rn "unserialize(base64_decode(" wp-content/themes/roisin/
    
  2. Identify Action Name:
    Look for the add_action call associated with the function containing the unserialize call.
  3. Generate Payload:
    Create a simple PHP object payload. For a PoC, we can target a class that might exist in the environment (e.g., WP_HTML_Token or similar) to trigger a __destruct call, or simply use an invalid class to see if the application logs an error.
    Example Payload Generation (Manual): O:8:"Exploit":0:{}
    Base64 Encoded: Tzo4OiJFeHBsb2l0IjpwOnt9
  4. Send Request:
    Construct the HTTP request using the http_request tool.

HTTP Request Template:

  • Method: POST
  • URL: http://[TARGET]/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=[ACTION_NAME]&nonce=[NONCE]&options=Tzo4OiJFeHBsb2l0IjpwOnt9

6. Test Data Setup

  1. Theme Installation: Ensure Roisin Theme v1.4 is installed and active.
  2. Public Content: Create at least one public post/page to ensure the theme's frontend assets and nonces are generated correctly.
  3. Verify Nonce Visibility: Check that the roisinElatedVars object is present in the page source.

7. Expected Results

  • If a non-existent class is injected (e.g., O:8:"Exploit":0:{}), the server may return a 500 error or a PHP warning in the debug.log stating: PHP Warning: unserialize(): Function ... [unserialized object of unknown class].
  • If a valid POP chain is found (e.g., via an installed plugin like WooCommerce), the successful exploit would result in the specific action defined by the gadget (e.g., file deletion or RCE).
  • The response should be consistent with the AJAX handler's behavior, but the side effects (logs or errors) will confirm deserialization occurred.

8. Verification Steps

  1. Check PHP Error Log:
    tail -n 50 wp-content/debug.log
    
    Look for: PHP Fatal error: unserialize(): Object of class __PHP_Incomplete_Class ... or similar messages indicating the payload was processed.
  2. Manual Verification via WP-CLI:
    If the payload is designed to modify an option or metadata, verify the change:
    wp option get [modified_option]
    

9. Alternative Approaches

  • Different Actions: If roisin_elated_get_sidebar is not the culprit, search for wp_ajax_nopriv hooks in the framework/ or inc/ directories and audit any that use $_POST or $_GET inside unserialize().
  • Payload Variation: Try different serialization formats. Sometimes themes use maybe_unserialize() on raw strings; if the input starts with a: or O:, it will trigger.
  • Missing Nonce: Check if the handler actually validates the nonce. If check_ajax_referer is missing or called with die=false without a subsequent check, the nonce acquisition step can be skipped.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Roisin theme for WordPress is vulnerable to unauthenticated PHP Object Injection due to the insecure use of the unserialize() function on base64-encoded user input within AJAX handlers. Attackers can exploit this to inject arbitrary PHP objects, which may lead to remote code execution or file deletion if a suitable POP chain is present in the environment.

Vulnerable Code

// From the theme's AJAX handler registration (likely in framework/modules/sidebars/sidebar-functions.php or similar)
add_action('wp_ajax_nopriv_roisin_elated_get_sidebar', 'roisin_elated_get_sidebar');
add_action('wp_ajax_roisin_elated_get_sidebar', 'roisin_elated_get_sidebar');

function roisin_elated_get_sidebar() {
    // ... logic ...
    if (isset($_POST['options'])) {
        // Vulnerable Sink
        $options = unserialize(base64_decode($_POST['options']));
    }
    // ... logic ...
}

Security Fix

--- a/framework/modules/sidebars/sidebar-functions.php
+++ b/framework/modules/sidebars/sidebar-functions.php
@@ -10,7 +10,7 @@
     if (isset($_POST['options'])) {
-        $options = unserialize(base64_decode($_POST['options']));
+        $options = json_decode(base64_decode($_POST['options']), true);
     }

Exploit Outline

The exploit targets the AJAX interface of the Roisin theme. An attacker first extracts a valid AJAX nonce (typically `roisinElatedVars.ajax_nonce`) from the source code of any public-facing page where the theme is active. The attacker then constructs a POST request to `/wp-admin/admin-ajax.php`. The request must include the `action` parameter (e.g., `roisin_elated_get_sidebar`), the valid `nonce`, and a malicious PHP object payload that is base64-encoded and assigned to the `options` (or `query_obj`) parameter. When the server processes the request, the handler decodes the base64 string and passes it directly into `unserialize()`, triggering the instantiation of the injected object and any associated magic methods like `__wakeup` or `__destruct`.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.